mirror of
https://github.com/SabreTools/BinaryObjectScanner.git
synced 2026-02-04 13:45:28 +00:00
Compare commits
64 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
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 |
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
|
||||
|
||||
@@ -10,8 +10,10 @@
|
||||
<LangVersion>latest</LangVersion>
|
||||
<Nullable>enable</Nullable>
|
||||
<SuppressTfmSupportBuildWarnings>true</SuppressTfmSupportBuildWarnings>
|
||||
<!-- <TreatWarningsAsErrors>true</TreatWarningsAsErrors> --> <!-- Can't be enabled because of external code -->
|
||||
<Version>3.1.2</Version>
|
||||
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
|
||||
<Version>3.1.9</Version>
|
||||
<!-- Mostly added due to external libraries -->
|
||||
<WarningsNotAsErrors>CS0162;CS0612;CS8600;CS8601;CS8602;CS8603;CS8604;CS8605;CS8618;CS8625;CS8634;CS8765;IL3000;NU5100</WarningsNotAsErrors>
|
||||
|
||||
<!-- Package Properties -->
|
||||
<Authors>Matt Nadareski</Authors>
|
||||
@@ -71,11 +73,9 @@
|
||||
</ItemGroup>
|
||||
<ItemGroup Condition="!$(TargetFramework.StartsWith(`net2`)) AND !$(TargetFramework.StartsWith(`net3`))">
|
||||
<PackageReference Include="OpenMcdf" Version="2.3.1" />
|
||||
<PackageReference Include="UnshieldSharp" Version="1.7.2" />
|
||||
</ItemGroup>
|
||||
<ItemGroup Condition="!$(TargetFramework.StartsWith(`net2`)) AND !$(TargetFramework.StartsWith(`net3`)) AND !$(TargetFramework.StartsWith(`net40`)) AND !$(TargetFramework.StartsWith(`net452`))">
|
||||
<PackageReference Include="SharpCompress" Version="0.36.0" />
|
||||
<PackageReference Include="SharpZipLib" Version="1.4.2" />
|
||||
<PackageReference Include="SharpCompress" Version="0.37.2" />
|
||||
<PackageReference Include="System.Text.Encoding.CodePages" Version="8.0.0" />
|
||||
</ItemGroup>
|
||||
<ItemGroup Condition="$(TargetFramework.StartsWith(`net4`)) AND !$(TargetFramework.StartsWith(`net40`))">
|
||||
@@ -83,13 +83,14 @@
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="SabreTools.Compression" Version="0.3.1" />
|
||||
<PackageReference Include="SabreTools.Hashing" Version="1.1.4" />
|
||||
<PackageReference Include="SabreTools.IO" Version="1.3.2" />
|
||||
<PackageReference Include="SabreTools.Compression" Version="0.5.1" />
|
||||
<PackageReference Include="SabreTools.Hashing" Version="1.2.0" />
|
||||
<PackageReference Include="SabreTools.IO" Version="1.4.8" />
|
||||
<PackageReference Include="SabreTools.Matching" Version="1.3.1" />
|
||||
<PackageReference Include="SabreTools.Models" Version="1.4.0" />
|
||||
<PackageReference Include="SabreTools.Serialization" Version="1.4.0" />
|
||||
<PackageReference Include="WiseUnpacker" Version="1.3.0" />
|
||||
<PackageReference Include="SabreTools.Models" Version="1.4.5" />
|
||||
<PackageReference Include="SabreTools.Serialization" Version="1.6.1" />
|
||||
<PackageReference Include="UnshieldSharp" Version="1.8.2" />
|
||||
<PackageReference Include="WiseUnpacker" Version="1.4.2" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
using BinaryObjectScanner.Interfaces;
|
||||
using BinaryObjectScanner.Utilities;
|
||||
using SabreTools.Serialization.Wrappers;
|
||||
|
||||
namespace BinaryObjectScanner
|
||||
{
|
||||
@@ -8,20 +8,22 @@ namespace BinaryObjectScanner
|
||||
/// <summary>
|
||||
/// Create an instance of a detectable based on file type
|
||||
/// </summary>
|
||||
public static IDetectable? CreateDetectable(SupportedFileType fileType)
|
||||
public static IDetectable? CreateDetectable(WrapperType fileType)
|
||||
{
|
||||
switch (fileType)
|
||||
{
|
||||
case SupportedFileType.AACSMediaKeyBlock: return new FileType.AACSMediaKeyBlock();
|
||||
case SupportedFileType.BDPlusSVM: return new FileType.BDPlusSVM();
|
||||
//case SupportedFileType.CIA: return new FileType.CIA();
|
||||
case SupportedFileType.Executable: return new FileType.Executable();
|
||||
case SupportedFileType.LDSCRYPT: return new FileType.LDSCRYPT();
|
||||
//case SupportedFileType.N3DS: return new FileType.N3DS();
|
||||
//case SupportedFileType.Nitro: return new FileType.Nitro();
|
||||
case SupportedFileType.PLJ: return new FileType.PLJ();
|
||||
case SupportedFileType.SFFS: return new FileType.SFFS();
|
||||
case SupportedFileType.Textfile: return new FileType.Textfile();
|
||||
case WrapperType.AACSMediaKeyBlock: return new FileType.AACSMediaKeyBlock();
|
||||
case WrapperType.BDPlusSVM: return new FileType.BDPlusSVM();
|
||||
//case WrapperType.CIA: return new FileType.CIA();
|
||||
case WrapperType.Executable: return new FileType.Executable();
|
||||
case WrapperType.LDSCRYPT: return new FileType.LDSCRYPT();
|
||||
//case WrapperType.N3DS: return new FileType.N3DS();
|
||||
//case WrapperType.Nitro: return new FileType.Nitro();
|
||||
case WrapperType.PlayJAudioFile: return new FileType.PLJ();
|
||||
case WrapperType.RealArcadeInstaller: return new FileType.RealArcadeInstaller();
|
||||
case WrapperType.RealArcadeMezzanine: return new FileType.RealArcadeMezzanine();
|
||||
case WrapperType.SFFS: return new FileType.SFFS();
|
||||
case WrapperType.Textfile: return new FileType.Textfile();
|
||||
default: return null;
|
||||
}
|
||||
}
|
||||
@@ -29,40 +31,40 @@ namespace BinaryObjectScanner
|
||||
/// <summary>
|
||||
/// Create an instance of an extractable based on file type
|
||||
/// </summary>
|
||||
public static IExtractable? CreateExtractable(SupportedFileType fileType)
|
||||
public static IExtractable? CreateExtractable(WrapperType fileType)
|
||||
{
|
||||
switch (fileType)
|
||||
{
|
||||
case SupportedFileType.BFPK: return new FileType.BFPK();
|
||||
case SupportedFileType.BSP: return new FileType.BSP();
|
||||
case SupportedFileType.BZip2: return new FileType.BZip2();
|
||||
case SupportedFileType.CFB: return new FileType.CFB();
|
||||
//case SupportedFileType.CIA: return new FileType.CIA();
|
||||
case SupportedFileType.GCF: return new FileType.GCF();
|
||||
case SupportedFileType.GZIP: return new FileType.GZIP();
|
||||
case SupportedFileType.InstallShieldArchiveV3: return new FileType.InstallShieldArchiveV3();
|
||||
case SupportedFileType.InstallShieldCAB: return new FileType.InstallShieldCAB();
|
||||
case SupportedFileType.MicrosoftCAB: return new FileType.MicrosoftCAB();
|
||||
case SupportedFileType.MicrosoftLZ: return new FileType.MicrosoftLZ();
|
||||
case SupportedFileType.MPQ: return new FileType.MPQ();
|
||||
//case SupportedFileType.N3DS: return new FileType.N3DS();
|
||||
//case SupportedFileType.NCF: return new FileType.NCF();
|
||||
//case SupportedFileType.Nitro: return new FileType.Nitro();
|
||||
case SupportedFileType.PAK: return new FileType.PAK();
|
||||
case SupportedFileType.PFF: return new FileType.PFF();
|
||||
case SupportedFileType.PKZIP: return new FileType.PKZIP();
|
||||
//case SupportedFileType.PLJ: return new FileType.PLJ();
|
||||
//case SupportedFileType.Quantum: return new FileType.Quantum();
|
||||
case SupportedFileType.RAR: return new FileType.RAR();
|
||||
case SupportedFileType.SevenZip: return new FileType.SevenZip();
|
||||
case SupportedFileType.SFFS: return new FileType.SFFS();
|
||||
case SupportedFileType.SGA: return new FileType.SGA();
|
||||
case SupportedFileType.TapeArchive: return new FileType.TapeArchive();
|
||||
case SupportedFileType.VBSP: return new FileType.VBSP();
|
||||
case SupportedFileType.VPK: return new FileType.VPK();
|
||||
case SupportedFileType.WAD: return new FileType.WAD();
|
||||
case SupportedFileType.XZ: return new FileType.XZ();
|
||||
case SupportedFileType.XZP: return new FileType.XZP();
|
||||
case WrapperType.BFPK: return new FileType.BFPK();
|
||||
case WrapperType.BSP: return new FileType.BSP();
|
||||
case WrapperType.BZip2: return new FileType.BZip2();
|
||||
case WrapperType.CFB: return new FileType.CFB();
|
||||
//case WrapperType.CIA: return new FileType.CIA();
|
||||
case WrapperType.GCF: return new FileType.GCF();
|
||||
case WrapperType.GZIP: return new FileType.GZIP();
|
||||
case WrapperType.InstallShieldArchiveV3: return new FileType.InstallShieldArchiveV3();
|
||||
case WrapperType.InstallShieldCAB: return new FileType.InstallShieldCAB();
|
||||
case WrapperType.MicrosoftCAB: return new FileType.MicrosoftCAB();
|
||||
case WrapperType.MicrosoftLZ: return new FileType.MicrosoftLZ();
|
||||
case WrapperType.MoPaQ: return new FileType.MPQ();
|
||||
//case WrapperType.N3DS: return new FileType.N3DS();
|
||||
//case WrapperType.NCF: return new FileType.NCF();
|
||||
//case WrapperType.Nitro: return new FileType.Nitro();
|
||||
case WrapperType.PAK: return new FileType.PAK();
|
||||
case WrapperType.PFF: return new FileType.PFF();
|
||||
case WrapperType.PKZIP: return new FileType.PKZIP();
|
||||
//case WrapperType.PlayJAudioFile: return new FileType.PLJ();
|
||||
//case WrapperType.Quantum: return new FileType.Quantum();
|
||||
case WrapperType.RAR: return new FileType.RAR();
|
||||
case WrapperType.SevenZip: return new FileType.SevenZip();
|
||||
case WrapperType.SFFS: return new FileType.SFFS();
|
||||
case WrapperType.SGA: return new FileType.SGA();
|
||||
case WrapperType.TapeArchive: return new FileType.TapeArchive();
|
||||
case WrapperType.VBSP: return new FileType.VBSP();
|
||||
case WrapperType.VPK: return new FileType.VPK();
|
||||
case WrapperType.WAD: return new FileType.WAD();
|
||||
case WrapperType.XZ: return new FileType.XZ();
|
||||
case WrapperType.XZP: return new FileType.XZP();
|
||||
default: return null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,7 +7,9 @@ using System.IO;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
#if NET40_OR_GREATER || NETCOREAPP
|
||||
using System.Threading.Tasks;
|
||||
#endif
|
||||
using BinaryObjectScanner.Interfaces;
|
||||
using BinaryObjectScanner.Utilities;
|
||||
using SabreTools.Serialization.Wrappers;
|
||||
|
||||
@@ -42,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);
|
||||
}
|
||||
|
||||
@@ -1,10 +1,6 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using BinaryObjectScanner.Interfaces;
|
||||
#if NET40_OR_GREATER || NETCOREAPP
|
||||
using UnshieldSharp.Archive;
|
||||
#endif
|
||||
|
||||
namespace BinaryObjectScanner.FileType
|
||||
{
|
||||
@@ -26,10 +22,6 @@ namespace BinaryObjectScanner.FileType
|
||||
/// <inheritdoc/>
|
||||
public string? Extract(Stream? stream, string file, bool includeDebug)
|
||||
{
|
||||
#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
|
||||
@@ -37,16 +29,16 @@ 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!);
|
||||
(byte[]? fileContents, string? error) = archive.Extract(cfile.Key);
|
||||
if (fileContents == null || !string.IsNullOrEmpty(error))
|
||||
continue;
|
||||
|
||||
@@ -68,7 +60,6 @@ namespace BinaryObjectScanner.FileType
|
||||
if (includeDebug) Console.WriteLine(ex);
|
||||
return null;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,9 +2,7 @@
|
||||
using System.IO;
|
||||
using System.Text.RegularExpressions;
|
||||
using BinaryObjectScanner.Interfaces;
|
||||
#if NET40_OR_GREATER || NETCOREAPP
|
||||
using UnshieldSharp.Cabinet;
|
||||
#endif
|
||||
|
||||
namespace BinaryObjectScanner.FileType
|
||||
{
|
||||
@@ -26,10 +24,6 @@ namespace BinaryObjectScanner.FileType
|
||||
/// <inheritdoc/>
|
||||
public string? Extract(Stream? stream, string file, bool includeDebug)
|
||||
{
|
||||
#if NET20 || NET35
|
||||
// Not supported for .NET Framework 2.0 or .NET Framework 3.5 due to library support
|
||||
return null;
|
||||
#else
|
||||
// Get the name of the first cabinet file or header
|
||||
var directory = Path.GetDirectoryName(file);
|
||||
string noExtension = Path.GetFileNameWithoutExtension(file);
|
||||
@@ -65,21 +59,21 @@ namespace BinaryObjectScanner.FileType
|
||||
Directory.CreateDirectory(tempPath);
|
||||
|
||||
var cabfile = InstallShieldCabinet.Open(file);
|
||||
if (cabfile == null)
|
||||
if (cabfile?.HeaderList == null)
|
||||
return null;
|
||||
|
||||
for (int i = 0; i < cabfile.FileCount; i++)
|
||||
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);
|
||||
string? filename = cabfile.HeaderList.GetFileName(i);
|
||||
tempFile = Path.Combine(tempPath, filename ?? string.Empty);
|
||||
}
|
||||
catch
|
||||
@@ -102,7 +96,6 @@ namespace BinaryObjectScanner.FileType
|
||||
if (includeDebug) Console.WriteLine(ex);
|
||||
return null;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -42,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))
|
||||
|
||||
@@ -42,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);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3,9 +3,7 @@ using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using BinaryObjectScanner.Interfaces;
|
||||
#if NET462_OR_GREATER || NETCOREAPP
|
||||
using ICSharpCode.SharpZipLib.Zip.Compression;
|
||||
#endif
|
||||
using SabreTools.Compression.zlib;
|
||||
|
||||
namespace BinaryObjectScanner.FileType
|
||||
{
|
||||
@@ -230,15 +228,26 @@ namespace BinaryObjectScanner.FileType
|
||||
}
|
||||
else
|
||||
{
|
||||
// Decompress the data
|
||||
#if NET462_OR_GREATER || NETCOREAPP
|
||||
// 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);
|
||||
#else
|
||||
data = new byte[outputFileSize];
|
||||
#endif
|
||||
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
|
||||
|
||||
@@ -26,6 +26,9 @@ namespace BinaryObjectScanner.FileType
|
||||
/// <inheritdoc/>
|
||||
public string? Extract(Stream? stream, string file, bool includeDebug)
|
||||
{
|
||||
if (stream == null)
|
||||
return null;
|
||||
|
||||
#if NET462_OR_GREATER || NETCOREAPP
|
||||
try
|
||||
{
|
||||
@@ -39,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);
|
||||
}
|
||||
|
||||
@@ -42,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);
|
||||
}
|
||||
|
||||
@@ -107,6 +107,11 @@ namespace BinaryObjectScanner.FileType
|
||||
// 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"))
|
||||
|
||||
@@ -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
|
||||
{
|
||||
|
||||
@@ -9,6 +9,7 @@ using System.Reflection;
|
||||
using System.Threading.Tasks;
|
||||
using BinaryObjectScanner.Interfaces;
|
||||
using BinaryObjectScanner.Utilities;
|
||||
using SabreTools.Serialization.Wrappers;
|
||||
using static BinaryObjectScanner.Utilities.Dictionary;
|
||||
|
||||
namespace BinaryObjectScanner
|
||||
@@ -62,7 +63,7 @@ namespace BinaryObjectScanner
|
||||
#endif
|
||||
|
||||
// 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
|
||||
#if NET20 || NET35
|
||||
@@ -108,7 +109,7 @@ 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>
|
||||
@@ -153,6 +154,198 @@ namespace BinaryObjectScanner
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Handle files based on an IExtractableMSDOSExecutable implementation
|
||||
/// </summary>
|
||||
/// <param name="impl">IExtractableMSDOSExecutable class representing the file type</param>
|
||||
/// <param name="fileName">Name of the source file of the stream, for tracking</param>
|
||||
/// <param name="mz">MSDOS to scan the contents of</param>
|
||||
/// <param name="scanner">Scanner object to use on extractable contents</param>
|
||||
/// <returns>Set of protections in file, null on error</returns>
|
||||
#if NET20 || NET35
|
||||
public static Dictionary<string, Queue<string>>? HandleExtractable(IExtractableMSDOSExecutable impl, string fileName, MSDOS mz, Scanner scanner)
|
||||
#else
|
||||
public static ConcurrentDictionary<string, ConcurrentQueue<string>>? HandleExtractable(IExtractableMSDOSExecutable impl, string fileName, MSDOS mz, Scanner scanner)
|
||||
#endif
|
||||
{
|
||||
// If the extractable file itself fails
|
||||
try
|
||||
{
|
||||
// Extract and get the output path
|
||||
var tempPath = impl.Extract(fileName, mz, scanner.IncludeDebug);
|
||||
if (tempPath == null)
|
||||
return null;
|
||||
|
||||
// Collect and format all found protections
|
||||
var subProtections = scanner.GetProtections(tempPath);
|
||||
|
||||
// If temp directory cleanup fails
|
||||
try
|
||||
{
|
||||
Directory.Delete(tempPath, true);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
if (scanner.IncludeDebug) Console.WriteLine(ex);
|
||||
}
|
||||
|
||||
// Prepare the returned protections
|
||||
StripFromKeys(subProtections, tempPath);
|
||||
PrependToKeys(subProtections, fileName);
|
||||
return subProtections;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
if (scanner.IncludeDebug) Console.WriteLine(ex);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Handle files based on an IExtractableLinearExecutable implementation
|
||||
/// </summary>
|
||||
/// <param name="impl">IExtractableLinearExecutable class representing the file type</param>
|
||||
/// <param name="fileName">Name of the source file of the stream, for tracking</param>
|
||||
/// <param name="lex">LinearExecutable to scan the contents of</param>
|
||||
/// <param name="scanner">Scanner object to use on extractable contents</param>
|
||||
/// <returns>Set of protections in file, null on error</returns>
|
||||
#if NET20 || NET35
|
||||
public static Dictionary<string, Queue<string>>? HandleExtractable(IExtractableLinearExecutable impl, string fileName, LinearExecutable lex, Scanner scanner)
|
||||
#else
|
||||
public static ConcurrentDictionary<string, ConcurrentQueue<string>>? HandleExtractable(IExtractableLinearExecutable impl, string fileName, LinearExecutable lex, Scanner scanner)
|
||||
#endif
|
||||
{
|
||||
// If the extractable file itself fails
|
||||
try
|
||||
{
|
||||
// Extract and get the output path
|
||||
var tempPath = impl.Extract(fileName, lex, scanner.IncludeDebug);
|
||||
if (tempPath == null)
|
||||
return null;
|
||||
|
||||
// Collect and format all found protections
|
||||
var subProtections = scanner.GetProtections(tempPath);
|
||||
|
||||
// If temp directory cleanup fails
|
||||
try
|
||||
{
|
||||
Directory.Delete(tempPath, true);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
if (scanner.IncludeDebug) Console.WriteLine(ex);
|
||||
}
|
||||
|
||||
// Prepare the returned protections
|
||||
StripFromKeys(subProtections, tempPath);
|
||||
PrependToKeys(subProtections, fileName);
|
||||
return subProtections;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
if (scanner.IncludeDebug) Console.WriteLine(ex);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Handle files based on an IExtractableNewExecutable implementation
|
||||
/// </summary>
|
||||
/// <param name="impl">IExtractableNewExecutable class representing the file type</param>
|
||||
/// <param name="fileName">Name of the source file of the stream, for tracking</param>
|
||||
/// <param name="nex">NewExecutable to scan the contents of</param>
|
||||
/// <param name="scanner">Scanner object to use on extractable contents</param>
|
||||
/// <returns>Set of protections in file, null on error</returns>
|
||||
#if NET20 || NET35
|
||||
public static Dictionary<string, Queue<string>>? HandleExtractable(IExtractableNewExecutable impl, string fileName, NewExecutable nex, Scanner scanner)
|
||||
#else
|
||||
public static ConcurrentDictionary<string, ConcurrentQueue<string>>? HandleExtractable(IExtractableNewExecutable impl, string fileName, NewExecutable nex, Scanner scanner)
|
||||
#endif
|
||||
{
|
||||
// If the extractable file itself fails
|
||||
try
|
||||
{
|
||||
// Extract and get the output path
|
||||
var tempPath = impl.Extract(fileName, nex, scanner.IncludeDebug);
|
||||
if (tempPath == null)
|
||||
return null;
|
||||
|
||||
// Collect and format all found protections
|
||||
var subProtections = scanner.GetProtections(tempPath);
|
||||
|
||||
// If temp directory cleanup fails
|
||||
try
|
||||
{
|
||||
Directory.Delete(tempPath, true);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
if (scanner.IncludeDebug) Console.WriteLine(ex);
|
||||
}
|
||||
|
||||
// Prepare the returned protections
|
||||
StripFromKeys(subProtections, tempPath);
|
||||
PrependToKeys(subProtections, fileName);
|
||||
return subProtections;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
if (scanner.IncludeDebug) Console.WriteLine(ex);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Handle files based on an IExtractablePortableExecutable implementation
|
||||
/// </summary>
|
||||
/// <param name="impl">IExtractablePortableExecutable class representing the file type</param>
|
||||
/// <param name="fileName">Name of the source file of the stream, for tracking</param>
|
||||
/// <param name="pex">PortableExecutable to scan the contents of</param>
|
||||
/// <param name="scanner">Scanner object to use on extractable contents</param>
|
||||
/// <returns>Set of protections in file, null on error</returns>
|
||||
#if NET20 || NET35
|
||||
public static Dictionary<string, Queue<string>>? HandleExtractable(IExtractablePortableExecutable impl, string fileName, PortableExecutable pex, Scanner scanner)
|
||||
#else
|
||||
public static ConcurrentDictionary<string, ConcurrentQueue<string>>? HandleExtractable(IExtractablePortableExecutable impl, string fileName, PortableExecutable pex, Scanner scanner)
|
||||
#endif
|
||||
{
|
||||
// If the extractable file itself fails
|
||||
try
|
||||
{
|
||||
// Extract and get the output path
|
||||
var tempPath = impl.Extract(fileName, pex, scanner.IncludeDebug);
|
||||
if (tempPath == null)
|
||||
return null;
|
||||
|
||||
// Collect and format all found protections
|
||||
var subProtections = scanner.GetProtections(tempPath);
|
||||
|
||||
// If temp directory cleanup fails
|
||||
try
|
||||
{
|
||||
Directory.Delete(tempPath, true);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
if (scanner.IncludeDebug) Console.WriteLine(ex);
|
||||
}
|
||||
|
||||
// Prepare the returned protections
|
||||
StripFromKeys(subProtections, tempPath);
|
||||
PrependToKeys(subProtections, fileName);
|
||||
return subProtections;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
if (scanner.IncludeDebug) Console.WriteLine(ex);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Handle files based on an IPathCheck implementation
|
||||
/// </summary>
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,4 @@
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using BinaryObjectScanner.Interfaces;
|
||||
using SabreTools.Matching;
|
||||
@@ -8,7 +7,7 @@ using SabreTools.Serialization.Wrappers;
|
||||
namespace BinaryObjectScanner.Packer
|
||||
{
|
||||
// TODO: Add extraction
|
||||
public class ASPack : IExtractable, IPortableExecutableCheck
|
||||
public class ASPack : IExtractablePortableExecutable, IPortableExecutableCheck
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
public string? CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug)
|
||||
@@ -51,19 +50,7 @@ namespace BinaryObjectScanner.Packer
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public string? Extract(string file, bool includeDebug)
|
||||
{
|
||||
if (!File.Exists(file))
|
||||
return null;
|
||||
|
||||
using (var fs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
|
||||
{
|
||||
return Extract(fs, file, includeDebug);
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public string? Extract(Stream? stream, string file, bool includeDebug)
|
||||
public string? Extract(string file, PortableExecutable pex, bool includeDebug)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using BinaryObjectScanner.Interfaces;
|
||||
using SabreTools.Serialization.Wrappers;
|
||||
@@ -8,7 +6,7 @@ namespace BinaryObjectScanner.Packer
|
||||
{
|
||||
// TODO: Add extraction
|
||||
// TODO: Verify that all versions are detected
|
||||
public class AdvancedInstaller : IExtractable, IPortableExecutableCheck
|
||||
public class AdvancedInstaller : IExtractablePortableExecutable, IPortableExecutableCheck
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
public string? CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug)
|
||||
@@ -30,19 +28,7 @@ namespace BinaryObjectScanner.Packer
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public string? Extract(string file, bool includeDebug)
|
||||
{
|
||||
if (!File.Exists(file))
|
||||
return null;
|
||||
|
||||
using (var fs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
|
||||
{
|
||||
return Extract(fs, file, includeDebug);
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public string? Extract(Stream? stream, string file, bool includeDebug)
|
||||
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;
|
||||
|
||||
@@ -8,7 +7,7 @@ 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
|
||||
public class Armadillo : IExtractablePortableExecutable, IPortableExecutableCheck
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
public string? CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug)
|
||||
@@ -42,19 +41,7 @@ namespace BinaryObjectScanner.Packer
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public string? Extract(string file, bool includeDebug)
|
||||
{
|
||||
if (!File.Exists(file))
|
||||
return null;
|
||||
|
||||
using (var fs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
|
||||
{
|
||||
return Extract(fs, file, includeDebug);
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public string? Extract(Stream? stream, string file, bool includeDebug)
|
||||
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,7 +7,7 @@ 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/>
|
||||
public string? CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug)
|
||||
@@ -34,19 +33,7 @@ namespace BinaryObjectScanner.Packer
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public string? Extract(string file, bool includeDebug)
|
||||
{
|
||||
if (!File.Exists(file))
|
||||
return null;
|
||||
|
||||
using (var fs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
|
||||
{
|
||||
return Extract(fs, file, includeDebug);
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public string? Extract(Stream? stream, string file, bool includeDebug)
|
||||
public string? Extract(string file, PortableExecutable pex, bool includeDebug)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -3,9 +3,7 @@ using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using BinaryObjectScanner.Interfaces;
|
||||
#if NET462_OR_GREATER || NETCOREAPP
|
||||
using ICSharpCode.SharpZipLib.Zip.Compression;
|
||||
#endif
|
||||
using SabreTools.Compression.zlib;
|
||||
using SabreTools.Matching;
|
||||
using SabreTools.Serialization.Wrappers;
|
||||
|
||||
@@ -14,7 +12,7 @@ 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/>
|
||||
public string? CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug)
|
||||
@@ -52,25 +50,10 @@ namespace BinaryObjectScanner.Packer
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public string? Extract(string file, bool includeDebug)
|
||||
{
|
||||
if (!File.Exists(file))
|
||||
return null;
|
||||
|
||||
using var fs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
|
||||
return Extract(fs, file, includeDebug);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public string? Extract(Stream? stream, string file, bool includeDebug)
|
||||
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)
|
||||
@@ -88,16 +71,34 @@ namespace BinaryObjectScanner.Packer
|
||||
try
|
||||
{
|
||||
// Inflate the data into the buffer
|
||||
#if NET462_OR_GREATER || NETCOREAPP
|
||||
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
|
||||
data = null;
|
||||
var temp = new byte[read];
|
||||
Array.Copy(data, 0, temp, 0, read);
|
||||
data = temp;
|
||||
#endif
|
||||
}
|
||||
catch
|
||||
@@ -107,7 +108,7 @@ namespace BinaryObjectScanner.Packer
|
||||
}
|
||||
}
|
||||
|
||||
// Otherwise, LZ is used via the Windows API
|
||||
// Otherwise, LZ is used
|
||||
else
|
||||
{
|
||||
try
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using BinaryObjectScanner.Interfaces;
|
||||
using SabreTools.Matching;
|
||||
using SabreTools.Serialization.Wrappers;
|
||||
@@ -10,7 +9,7 @@ namespace BinaryObjectScanner.Packer
|
||||
// TODO: Detect 3.15 and up (maybe looking for `Metamorphism`)
|
||||
// TODO: Add extraction
|
||||
// https://raw.githubusercontent.com/wolfram77web/app-peid/master/userdb.txt
|
||||
public class EXEStealth : IContentCheck, IExtractable, IPortableExecutableCheck
|
||||
public class EXEStealth : IContentCheck, IExtractablePortableExecutable, IPortableExecutableCheck
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
public string? CheckContents(string file, byte[] fileContent, bool includeDebug)
|
||||
@@ -75,19 +74,7 @@ namespace BinaryObjectScanner.Packer
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public string? Extract(string file, bool includeDebug)
|
||||
{
|
||||
if (!File.Exists(file))
|
||||
return null;
|
||||
|
||||
using (var fs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
|
||||
{
|
||||
return Extract(fs, file, includeDebug);
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public string? Extract(Stream? stream, string file, bool includeDebug)
|
||||
public string? Extract(string file, PortableExecutable pex, bool includeDebug)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -11,7 +11,7 @@ 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/>
|
||||
public string? CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug)
|
||||
@@ -29,25 +29,12 @@ namespace BinaryObjectScanner.Packer
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public string? Extract(string file, bool includeDebug)
|
||||
{
|
||||
if (!File.Exists(file))
|
||||
return null;
|
||||
|
||||
using (var fs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
|
||||
{
|
||||
return Extract(fs, file, includeDebug);
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public string? Extract(Stream? stream, string file, bool includeDebug)
|
||||
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
|
||||
@@ -74,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,7 +6,7 @@ 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/>
|
||||
public string? CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug)
|
||||
@@ -33,19 +31,7 @@ namespace BinaryObjectScanner.Packer
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public string? Extract(string file, bool includeDebug)
|
||||
{
|
||||
if (!File.Exists(file))
|
||||
return null;
|
||||
|
||||
using (var fs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
|
||||
{
|
||||
return Extract(fs, file, includeDebug);
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public string? Extract(Stream? stream, string file, bool includeDebug)
|
||||
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,7 +9,7 @@ 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/>
|
||||
public string? CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug)
|
||||
@@ -32,19 +31,7 @@ namespace BinaryObjectScanner.Packer
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public string? Extract(string file, bool includeDebug)
|
||||
{
|
||||
if (!File.Exists(file))
|
||||
return null;
|
||||
|
||||
using (var fs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
|
||||
{
|
||||
return Extract(fs, file, includeDebug);
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public string? Extract(Stream? stream, string file, bool includeDebug)
|
||||
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 BinaryObjectScanner.Interfaces;
|
||||
using SabreTools.Matching;
|
||||
@@ -9,7 +8,7 @@ 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/>
|
||||
public string? CheckNewExecutable(string file, NewExecutable nex, bool includeDebug)
|
||||
@@ -54,19 +53,7 @@ namespace BinaryObjectScanner.Packer
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public string? Extract(string file, bool includeDebug)
|
||||
{
|
||||
if (!File.Exists(file))
|
||||
return null;
|
||||
|
||||
using (var fs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
|
||||
{
|
||||
return Extract(fs, file, includeDebug);
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public string? Extract(Stream? stream, string file, bool includeDebug)
|
||||
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;
|
||||
|
||||
@@ -7,7 +6,7 @@ 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/>
|
||||
public string? CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug)
|
||||
@@ -29,19 +28,7 @@ namespace BinaryObjectScanner.Packer
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public string? Extract(string file, bool includeDebug)
|
||||
{
|
||||
if (!File.Exists(file))
|
||||
return null;
|
||||
|
||||
using (var fs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
|
||||
{
|
||||
return Extract(fs, file, includeDebug);
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public string? Extract(Stream? stream, string file, bool includeDebug)
|
||||
public string? Extract(string file, PortableExecutable pex, bool includeDebug)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using BinaryObjectScanner.Interfaces;
|
||||
using SabreTools.Serialization.Wrappers;
|
||||
@@ -8,7 +6,7 @@ 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/>
|
||||
@@ -31,19 +29,7 @@ namespace BinaryObjectScanner.Packer
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public string? Extract(string file, bool includeDebug)
|
||||
{
|
||||
if (!File.Exists(file))
|
||||
return null;
|
||||
|
||||
using (var fs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
|
||||
{
|
||||
return Extract(fs, file, includeDebug);
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public string? Extract(Stream? stream, string file, bool includeDebug)
|
||||
public string? Extract(string file, PortableExecutable pex, bool includeDebug)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -1,12 +1,11 @@
|
||||
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/>
|
||||
public string? CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug)
|
||||
@@ -34,19 +33,7 @@ namespace BinaryObjectScanner.Packer
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public string? Extract(string file, bool includeDebug)
|
||||
{
|
||||
if (!File.Exists(file))
|
||||
return null;
|
||||
|
||||
using (var fs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
|
||||
{
|
||||
return Extract(fs, file, includeDebug);
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public string? Extract(Stream? stream, string file, bool includeDebug)
|
||||
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,7 +7,7 @@ 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/>
|
||||
public string? CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug)
|
||||
@@ -48,23 +47,11 @@ namespace BinaryObjectScanner.Packer
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public string? Extract(string file, bool includeDebug)
|
||||
{
|
||||
if (!File.Exists(file))
|
||||
return null;
|
||||
|
||||
using (var fs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
|
||||
{
|
||||
return Extract(fs, file, includeDebug);
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public string? Extract(Stream? stream, string file, bool includeDebug)
|
||||
public string? Extract(string file, PortableExecutable pex, bool includeDebug)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
private string GetVersion(PortableExecutable pex)
|
||||
{
|
||||
// Check the internal versions
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using BinaryObjectScanner.Interfaces;
|
||||
using SabreTools.Serialization.Wrappers;
|
||||
@@ -7,7 +5,7 @@ using SabreTools.Serialization.Wrappers;
|
||||
namespace BinaryObjectScanner.Packer
|
||||
{
|
||||
// TODO: Add extraction
|
||||
public class NSIS : IExtractable, IPortableExecutableCheck
|
||||
public class NSIS : IExtractablePortableExecutable, IPortableExecutableCheck
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
public string? CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug)
|
||||
@@ -33,19 +31,7 @@ namespace BinaryObjectScanner.Packer
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public string? Extract(string file, bool includeDebug)
|
||||
{
|
||||
if (!File.Exists(file))
|
||||
return null;
|
||||
|
||||
using (var fs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
|
||||
{
|
||||
return Extract(fs, file, includeDebug);
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public string? Extract(Stream? stream, string file, bool includeDebug)
|
||||
public string? Extract(string file, PortableExecutable pex, bool includeDebug)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -14,7 +14,7 @@ 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/>
|
||||
@@ -37,20 +37,7 @@ namespace BinaryObjectScanner.Packer
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public string? Extract(string file, bool includeDebug)
|
||||
{
|
||||
// TODO: Add extraction
|
||||
if (!File.Exists(file))
|
||||
return null;
|
||||
|
||||
using (var fs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
|
||||
{
|
||||
return Extract(fs, file, includeDebug);
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public string? Extract(Stream? stream, string file, bool includeDebug)
|
||||
public string? Extract(string file, PortableExecutable pex, bool includeDebug)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -1,12 +1,11 @@
|
||||
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/>
|
||||
public string? CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug)
|
||||
@@ -42,19 +41,7 @@ namespace BinaryObjectScanner.Packer
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public string? Extract(string file, bool includeDebug)
|
||||
{
|
||||
if (!File.Exists(file))
|
||||
return null;
|
||||
|
||||
using (var fs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
|
||||
{
|
||||
return Extract(fs, file, includeDebug);
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public string? Extract(Stream? stream, string file, bool includeDebug)
|
||||
public string? Extract(string file, PortableExecutable pex, bool includeDebug)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -1,12 +1,11 @@
|
||||
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/>
|
||||
public string? CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug)
|
||||
@@ -25,19 +24,7 @@ namespace BinaryObjectScanner.Packer
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public string? Extract(string file, bool includeDebug)
|
||||
{
|
||||
if (!File.Exists(file))
|
||||
return null;
|
||||
|
||||
using (var fs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
|
||||
{
|
||||
return Extract(fs, file, includeDebug);
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public string? Extract(Stream? stream, string file, bool includeDebug)
|
||||
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,7 +7,7 @@ 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/>
|
||||
public string? CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug)
|
||||
@@ -39,23 +38,11 @@ namespace BinaryObjectScanner.Packer
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public string? Extract(string file, bool includeDebug)
|
||||
{
|
||||
if (!File.Exists(file))
|
||||
return null;
|
||||
|
||||
using (var fs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
|
||||
{
|
||||
return Extract(fs, file, includeDebug);
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public string? Extract(Stream? stream, string file, bool includeDebug)
|
||||
public string? Extract(string file, PortableExecutable pex, bool includeDebug)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
private string GetVersion(PortableExecutable pex)
|
||||
{
|
||||
// Check the product version explicitly
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using BinaryObjectScanner.Interfaces;
|
||||
using SabreTools.Serialization.Wrappers;
|
||||
@@ -6,7 +5,7 @@ using SabreTools.Serialization.Wrappers;
|
||||
namespace BinaryObjectScanner.Packer
|
||||
{
|
||||
// TODO: Add extraction
|
||||
public class SevenZipSFX : IExtractable, IPortableExecutableCheck
|
||||
public class SevenZipSFX : IExtractablePortableExecutable, IPortableExecutableCheck
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
public string? CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug)
|
||||
@@ -46,19 +45,7 @@ namespace BinaryObjectScanner.Packer
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public string? Extract(string file, bool includeDebug)
|
||||
{
|
||||
if (!File.Exists(file))
|
||||
return null;
|
||||
|
||||
using (var fs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
|
||||
{
|
||||
return Extract(fs, file, includeDebug);
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public string? Extract(Stream? stream, string file, bool includeDebug)
|
||||
public string? Extract(string file, PortableExecutable pex, bool includeDebug)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
using System.IO;
|
||||
using BinaryObjectScanner.Interfaces;
|
||||
using SabreTools.Serialization.Wrappers;
|
||||
|
||||
@@ -6,7 +5,7 @@ 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/>
|
||||
public string? CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug)
|
||||
@@ -26,19 +25,7 @@ namespace BinaryObjectScanner.Packer
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public string? Extract(string file, bool includeDebug)
|
||||
{
|
||||
if (!File.Exists(file))
|
||||
return null;
|
||||
|
||||
using (var fs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
|
||||
{
|
||||
return Extract(fs, file, includeDebug);
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public string? Extract(Stream? stream, string file, bool includeDebug)
|
||||
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,7 +9,7 @@ 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);
|
||||
|
||||
@@ -64,19 +63,7 @@ namespace BinaryObjectScanner.Packer
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public string? Extract(string file, bool includeDebug)
|
||||
{
|
||||
if (!File.Exists(file))
|
||||
return null;
|
||||
|
||||
using (var fs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
|
||||
{
|
||||
return Extract(fs, file, includeDebug);
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public string? Extract(Stream? stream, string file, bool includeDebug)
|
||||
public string? Extract(string file, PortableExecutable pex, bool includeDebug)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -11,7 +11,7 @@ using SharpCompress.Readers;
|
||||
|
||||
namespace BinaryObjectScanner.Packer
|
||||
{
|
||||
public class WinRARSFX : IExtractable, IPortableExecutableCheck
|
||||
public class WinRARSFX : IExtractablePortableExecutable, IPortableExecutableCheck
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
public string? CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug)
|
||||
@@ -33,17 +33,7 @@ namespace BinaryObjectScanner.Packer
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public string? Extract(string file, bool includeDebug)
|
||||
{
|
||||
if (!File.Exists(file))
|
||||
return null;
|
||||
|
||||
using var fs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
|
||||
return Extract(fs, file, includeDebug);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public string? Extract(Stream? stream, string file, bool includeDebug)
|
||||
public string? Extract(string file, PortableExecutable pex, bool includeDebug)
|
||||
{
|
||||
#if NET462_OR_GREATER || NETCOREAPP
|
||||
try
|
||||
@@ -61,10 +51,14 @@ namespace BinaryObjectScanner.Packer
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
@@ -11,7 +11,7 @@ using SharpCompress.Archives.Zip;
|
||||
|
||||
namespace BinaryObjectScanner.Packer
|
||||
{
|
||||
public class WinZipSFX : IExtractable, INewExecutableCheck, IPortableExecutableCheck
|
||||
public class WinZipSFX : IExtractableNewExecutable, IExtractablePortableExecutable, INewExecutableCheck, IPortableExecutableCheck
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
public string? CheckNewExecutable(string file, NewExecutable nex, bool includeDebug)
|
||||
@@ -63,39 +63,48 @@ namespace BinaryObjectScanner.Packer
|
||||
// TODO: Find a way to generically detect 2.X versions and improve exact version detection for SFX PE versions bundled with WinZip 11+
|
||||
|
||||
/// <inheritdoc/>
|
||||
public string? Extract(string file, bool includeDebug)
|
||||
{
|
||||
if (!File.Exists(file))
|
||||
return null;
|
||||
|
||||
using var fs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
|
||||
return Extract(fs, file, includeDebug);
|
||||
}
|
||||
public string? Extract(string file, NewExecutable nex, bool includeDebug)
|
||||
=> Extract(file, includeDebug);
|
||||
|
||||
/// <inheritdoc/>
|
||||
public string? Extract(Stream? stream, string file, bool includeDebug)
|
||||
public string? Extract(string file, PortableExecutable pex, bool includeDebug)
|
||||
=> Extract(file, includeDebug);
|
||||
|
||||
/// <summary>
|
||||
/// Handle common extraction between executable types
|
||||
/// </summary>
|
||||
/// <inheritdoc/>
|
||||
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)
|
||||
@@ -103,9 +112,9 @@ namespace BinaryObjectScanner.Packer
|
||||
if (includeDebug) Console.WriteLine(ex);
|
||||
}
|
||||
}
|
||||
|
||||
return tempPath;
|
||||
}
|
||||
|
||||
return tempPath;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
@@ -122,7 +131,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
|
||||
private string? GetNEHeaderVersion(NewExecutable nex)
|
||||
private static string? GetNEHeaderVersion(NewExecutable nex)
|
||||
{
|
||||
#region 2.0 Variants
|
||||
|
||||
@@ -680,7 +689,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
|
||||
private string? GetPEExportDirectoryVersion(PortableExecutable pex)
|
||||
private static string? GetPEExportDirectoryVersion(PortableExecutable pex)
|
||||
{
|
||||
string sfxFileName = pex.Model.ExportTable?.ExportDirectoryTable?.Name ?? string.Empty;
|
||||
uint sfxTimeDateStamp = pex.Model.ExportTable?.ExportDirectoryTable?.TimeDateStamp ?? uint.MaxValue;
|
||||
|
||||
@@ -3,15 +3,16 @@ 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.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/>
|
||||
public string? CheckNewExecutable(string file, NewExecutable nex, bool includeDebug)
|
||||
@@ -73,33 +74,138 @@ namespace BinaryObjectScanner.Packer
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public string? Extract(string file, bool includeDebug)
|
||||
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.ReadWrite))
|
||||
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/>
|
||||
public string? Extract(Stream? stream, string file, bool includeDebug)
|
||||
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)
|
||||
{
|
||||
@@ -209,202 +315,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>
|
||||
private string? ExtractNewExecutable(NewExecutable nex, string file, bool includeDebug)
|
||||
{
|
||||
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>
|
||||
private string? ExtractPortableExecutable(PortableExecutable pex, string file, bool includeDebug)
|
||||
{
|
||||
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,13 +1,11 @@
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Linq;
|
||||
using BinaryObjectScanner.Interfaces;
|
||||
using SabreTools.Serialization.Wrappers;
|
||||
|
||||
namespace BinaryObjectScanner.Packer
|
||||
{
|
||||
// TODO: Add extraction
|
||||
public class dotFuscator : IExtractable, IPortableExecutableCheck
|
||||
public class dotFuscator : IExtractablePortableExecutable, IPortableExecutableCheck
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
public string? CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug)
|
||||
@@ -29,19 +27,7 @@ namespace BinaryObjectScanner.Packer
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public string? Extract(string file, bool includeDebug)
|
||||
{
|
||||
if (!File.Exists(file))
|
||||
return null;
|
||||
|
||||
using (var fs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
|
||||
{
|
||||
return Extract(fs, file, includeDebug);
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public string? Extract(Stream? stream, string file, bool includeDebug)
|
||||
public string? Extract(string file, PortableExecutable pex, bool includeDebug)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -23,7 +23,7 @@ namespace System
|
||||
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;
|
||||
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>
|
||||
@@ -73,7 +73,7 @@ namespace System
|
||||
{
|
||||
// Post the processing to the sync context.
|
||||
// (If T is a value type, it will get boxed here.)
|
||||
_synchronizationContext.Post(_invokeHandlers, value);
|
||||
_synchronizationContext?.Post(_invokeHandlers, value);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,11 @@
|
||||
using System;
|
||||
#if NET40_OR_GREATER || NETCOREAPP
|
||||
using System.Collections.Concurrent;
|
||||
#endif
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Security.Principal;
|
||||
using SabreTools.Matching;
|
||||
using SabreTools.Serialization.Wrappers;
|
||||
|
||||
namespace BinaryObjectScanner.Protection
|
||||
@@ -16,12 +23,96 @@ namespace BinaryObjectScanner.Protection
|
||||
if (sections == null)
|
||||
return null;
|
||||
|
||||
// Found in "IsSvcInstDanceEJay7.dll" in IA item "computer200709dvd" (Dance eJay 7).
|
||||
var name = pex.ProductName;
|
||||
|
||||
// Found in "IsSvcInstDanceEJay7.dll" in IA item "computer200709dvd" (Dance eJay 7).
|
||||
if (name?.Equals("FLEXnet Activation Toolkit", StringComparison.OrdinalIgnoreCase) == true)
|
||||
return $"FLEXnet";
|
||||
return "FLEXnet";
|
||||
|
||||
// Found in "INSTALLS.EXE", "LMGR326B.DLL", "LMGRD.EXE", and "TAKEFIVE.EXE" in IA item "prog-17_202403".
|
||||
if (name?.Equals("Globetrotter Software Inc lmgr326b Flexlm", StringComparison.OrdinalIgnoreCase) == true)
|
||||
return $"FlexLM {pex.ProductVersion}";
|
||||
|
||||
// Generic case to catch unknown versions.
|
||||
if (name?.Contains("Flexlm") == true)
|
||||
return "FlexLM (Unknown Version - Please report to us on GitHub)";
|
||||
|
||||
name = pex.FileDescription;
|
||||
|
||||
// Found in "INSTALLS.EXE", "LMGR326B.DLL", "LMGRD.EXE", and "TAKEFIVE.EXE" in IA item "prog-17_202403".
|
||||
if (name?.Equals("lmgr326b", StringComparison.OrdinalIgnoreCase) == true)
|
||||
return $"FlexLM {pex.ProductVersion}";
|
||||
|
||||
name = pex.LegalTrademarks;
|
||||
|
||||
// Found in "INSTALLS.EXE", "LMGR326B.DLL", "LMGRD.EXE", and "TAKEFIVE.EXE" in IA item "prog-17_202403".
|
||||
if (name?.Equals("Flexible License Manager,FLEXlm,Globetrotter,FLEXID", StringComparison.OrdinalIgnoreCase) == true)
|
||||
return $"FlexLM {pex.ProductVersion}";
|
||||
|
||||
if (name?.Contains("FLEXlm") == true)
|
||||
return $"FlexLM {pex.ProductVersion}";
|
||||
|
||||
name = pex.OriginalFilename;
|
||||
|
||||
// Found in "INSTALLS.EXE", "LMGR326B.DLL", "LMGRD.EXE", and "TAKEFIVE.EXE" in IA item "prog-17_202403".
|
||||
// It isn't known why these various executables have the same original filename.
|
||||
if (name?.Equals("lmgr326b.dll", StringComparison.OrdinalIgnoreCase) == true)
|
||||
return $"FlexLM {pex.ProductVersion}";
|
||||
|
||||
// Get the .data/DATA section strings, if they exist
|
||||
var strs = pex.GetFirstSectionStrings(".data") ?? pex.GetFirstSectionStrings("DATA");
|
||||
if (strs != null)
|
||||
{
|
||||
// Found in "FLEXLM.CPL", "INSTALLS.EXE", "LMGR326B.DLL", "LMGRD.EXE", and "TAKEFIVE.EXE" in IA item "prog-17_202403".
|
||||
if (strs.Any(s => s.Contains("FLEXlm License Manager")))
|
||||
return "FlexLM";
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="Interfaces.IPathCheck.CheckDirectoryPath(string, IEnumerable{string})"/>
|
||||
#if NET20 || NET35
|
||||
internal Queue<string> FLEXNetCheckDirectoryPath(string path, IEnumerable<string>? files)
|
||||
#else
|
||||
internal ConcurrentQueue<string> FLEXNetDirectoryPath(string path, IEnumerable<string>? files)
|
||||
#endif
|
||||
{
|
||||
var matchers = new List<PathMatchSet>
|
||||
{
|
||||
// Found in IA item "prog-17_202403".
|
||||
new(new PathMatch("FlexLM-6.1F", useEndsWith: true), "FlexLM 6.1f"),
|
||||
new(new PathMatch("FlexLM", useEndsWith: true), "FlexLM"),
|
||||
new(new PathMatch("FLexLM_Licensing.wri", useEndsWith: true), "FlexLM"),
|
||||
new(new PathMatch("LMGR326B.DLL", useEndsWith: true), "FlexLM"),
|
||||
new(new PathMatch("FLEXLM.CPL", useEndsWith: true), "FlexLM"),
|
||||
new(new PathMatch("LMGRD.EXE", useEndsWith: true), "FlexLM"),
|
||||
new(new PathMatch("LMGRD95.EXE", useEndsWith: true), "FlexLM"),
|
||||
new(new PathMatch("LMUTIL.EXE", useEndsWith: true), "FlexLM"),
|
||||
new(new PathMatch("READFLEX.WRI", useEndsWith: true), "FlexLM"),
|
||||
};
|
||||
|
||||
return MatchUtil.GetAllMatches(files, matchers, any: false);
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="Interfaces.IPathCheck.CheckFilePath(string)"/>
|
||||
internal string? FLEXNetCheckFilePath(string path)
|
||||
{
|
||||
var matchers = new List<PathMatchSet>
|
||||
{
|
||||
// Found in IA item "prog-17_202403".
|
||||
new(new PathMatch("FlexLM-6.1F", useEndsWith: true), "FlexLM 6.1f"),
|
||||
new(new PathMatch("FlexLM", useEndsWith: true), "FlexLM"),
|
||||
new(new PathMatch("FLexLM_Licensing.wri", useEndsWith: true), "FlexLM"),
|
||||
new(new PathMatch("LMGR326B.DLL", useEndsWith: true), "FlexLM"),
|
||||
new(new PathMatch("FLEXLM.CPL", useEndsWith: true), "FlexLM"),
|
||||
new(new PathMatch("LMGRD.EXE", useEndsWith: true), "FlexLM"),
|
||||
new(new PathMatch("LMGRD95.EXE", useEndsWith: true), "FlexLM"),
|
||||
new(new PathMatch("LMUTIL.EXE", useEndsWith: true), "FlexLM"),
|
||||
new(new PathMatch("READFLEX.WRI", useEndsWith: true), "FlexLM"),
|
||||
};
|
||||
|
||||
return MatchUtil.GetFirstMatch(path, matchers, any: true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,7 +7,7 @@ using System.IO;
|
||||
using System.Linq;
|
||||
using BinaryObjectScanner.Interfaces;
|
||||
using BinaryObjectScanner.Utilities;
|
||||
using SabreTools.IO;
|
||||
using SabreTools.IO.Extensions;
|
||||
using SabreTools.Matching;
|
||||
using SabreTools.Serialization.Wrappers;
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@ using System.Collections.Concurrent;
|
||||
#endif
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using BinaryObjectScanner.Interfaces;
|
||||
using SabreTools.Matching;
|
||||
using SabreTools.Serialization.Wrappers;
|
||||
@@ -15,16 +16,123 @@ namespace BinaryObjectScanner.Protection
|
||||
/// Rainbow Sentinel SuperPro: https://www.rainbow.com.my/superpro.php
|
||||
/// TODO: Investigate other versions/products.
|
||||
/// TODO: See if this is at all related to https://cpl.thalesgroup.com/software-monetization/all-products/sentinel-hl.
|
||||
/// TODO: Investigate the possible integration between FlexLM and Rainbow Sentinel in IA item "prog-17_202403".
|
||||
/// TODO: Investigate the "NetSentinel Protection System" found in "NSRVOM.EXE" and "NSRVGX.EXE" in IA item "czchip199707cd".
|
||||
/// TODO: Investigate "sntnlusb.sys" (https://www.rainbow.com.my/document/endusertroubleshooting.pdf).
|
||||
///
|
||||
/// Versions:
|
||||
/// Rainbow Sentinel PD-15: IA items "ASMEsMechanicalEngineeringToolkit1997December" and "aplicaciones-windows".
|
||||
/// Rainbow Sentinel PD-5.1: IA items "pcwkcd-1296, "CHIPTRMart97", and "bugcd199801".
|
||||
/// Rainbow Sentinel PD-5.1e (Beta): IA item "CHIPTRMart97".
|
||||
/// Rainbow Sentinel PD-5.37: File "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".
|
||||
/// Rainbow Sentinel PD-5.39: IA item "chip-cds-2001-08".
|
||||
/// Rainbow Sentinel PD-15: IA items "ASMEsMechanicalEngineeringToolkit1997December", "aplicaciones-windows", and "ASMEsMechanicalEngineeringToolkit1997December".
|
||||
/// Rainbow Sentinel PD-17: IA item "czchip199707cd".
|
||||
/// Rainbow Sentinel PD-30: BA entry "Autodesk AutoCAD LT 98 (1998) (CD) [English] [Dutch]" and IA item "auto-cad-r14-cdrom".
|
||||
/// Rainbow Sentinel PD-31: BA entry "Autodesk AutoCAD LT 98 (1998) (CD) [English] [Dutch]" and IA item "auto-cad-r14-cdrom".
|
||||
///
|
||||
/// Rainbow Sentinel SuperPro 5.0: IA items "chip-cds-2001-08".
|
||||
/// Rainbow Sentinel SuperPro 5.1: IA items "ASMEsMechanicalEngineeringToolkit1997December" and "aplicaciones-windows".
|
||||
///
|
||||
/// Rainbow SentinelPro 5.1: IA item "pcwkcd-1296".
|
||||
///
|
||||
/// Rainbow NetSentinel: IA item "czchip199707cd".
|
||||
/// </summary>
|
||||
public class RainbowSentinel : IPathCheck, IPortableExecutableCheck
|
||||
public class RainbowSentinel : IPathCheck, INewExecutableCheck, IPortableExecutableCheck
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
public string? CheckNewExecutable(string file, NewExecutable nex, bool includeDebug)
|
||||
{
|
||||
// TODO: Don't read entire file
|
||||
var data = nex.ReadArbitraryRange();
|
||||
if (data == null)
|
||||
return null;
|
||||
|
||||
// TODO: Figure out what NE section this lives in
|
||||
var neMatchSets = new List<ContentMatchSet>
|
||||
{
|
||||
// SentinelPro Windows Driver DLL
|
||||
// Found in "SSWIN.dll" in IA item "pcwkcd-1296".
|
||||
new(new byte?[]
|
||||
{
|
||||
0x53, 0x65, 0x6E, 0x74, 0x69, 0x6E, 0x65, 0x6C,
|
||||
0x50, 0x72, 0x6F, 0x20, 0x57, 0x69, 0x6E, 0x64,
|
||||
0x6F, 0x77, 0x73, 0x20, 0x44, 0x72, 0x69, 0x76,
|
||||
0x65, 0x72, 0x20, 0x44, 0x4C, 0x4C
|
||||
}, "Rainbow SentinelPro"),
|
||||
|
||||
// Sentinel Device Driver Version <20>PD-5.17
|
||||
// Found in "SENTINEL.SYS" in IA item "czchip199707cd".
|
||||
new(new byte?[]
|
||||
{
|
||||
0x53, 0x65, 0x6E, 0x74, 0x69, 0x6E, 0x65, 0x6C,
|
||||
0x20, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x20,
|
||||
0x44, 0x72, 0x69, 0x76, 0x65, 0x72, 0x20, 0x56,
|
||||
0x65, 0x72, 0x73, 0x69, 0x6F, 0x6E, 0x20, 0x00,
|
||||
0x50, 0x44, 0x2D, 0x35, 0x2E, 0x31, 0x37
|
||||
}, "Rainbow Sentinel PD-5.17"),
|
||||
|
||||
// NetSentinel OS/2 security server
|
||||
// Found in "NSRVOM.EXE" in IA item "czchip199707cd".
|
||||
new(new byte?[]
|
||||
{
|
||||
0x4E, 0x65, 0x74, 0x53, 0x65, 0x6E, 0x74, 0x69,
|
||||
0x6E, 0x65, 0x6C, 0x20, 0x4F, 0x53, 0x2F, 0x32,
|
||||
0x20, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72
|
||||
}, "Rainbow NetSentinel Server for OS/2"),
|
||||
|
||||
// NetSentinel Monitor
|
||||
// Found in "OS2MON.EXE" in IA item "czchip199707cd".
|
||||
new(new byte?[]
|
||||
{
|
||||
0x4E, 0x65, 0x74, 0x53, 0x65, 0x6E, 0x74, 0x69,
|
||||
0x6E, 0x65, 0x6C, 0x20, 0x20, 0x4D, 0x6F, 0x6E,
|
||||
0x69, 0x74, 0x6F, 0x72
|
||||
}, "Rainbow NetSentinel Monitor"),
|
||||
|
||||
// Sentinel Device Driver
|
||||
// Generic case to catch unknown versions.
|
||||
// TODO: Add version parsing for this check.
|
||||
new (new byte?[]
|
||||
{
|
||||
0x53, 0x65, 0x6E, 0x74, 0x69, 0x6E, 0x65, 0x6C,
|
||||
0x20, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x20,
|
||||
0x44, 0x72, 0x69, 0x76, 0x65, 0x72, 0x20, 0x56,
|
||||
0x65, 0x72, 0x73, 0x69, 0x6F, 0x6E, 0x20, 0x00,
|
||||
0x50, 0x44, 0x2D, 0x35, 0x2E, 0x31, 0x37
|
||||
}, "Rainbow Sentinel (Unknown Version - Please report this to us on GitHub)"),
|
||||
};
|
||||
|
||||
var match = MatchUtil.GetFirstMatch(file, data, neMatchSets, includeDebug);
|
||||
if (!string.IsNullOrEmpty(match))
|
||||
return match;
|
||||
|
||||
// Check the nonresident-name table
|
||||
// Found in "SSWIN.dll" in IA item "pcwkcd-1296".
|
||||
bool nonresidentNameTableEntries = nex.Model.NonResidentNameTable?
|
||||
.Select(nrnte => nrnte?.NameString == null ? string.Empty : Encoding.ASCII.GetString(nrnte.NameString))
|
||||
.Any(s => s.Contains("SentinelPro Windows Driver DLL")) ?? false;
|
||||
if (nonresidentNameTableEntries)
|
||||
return "Rainbow SentinelPro";
|
||||
|
||||
// Found in "INSTALL.EXE" in IA item "czchip199707cd".
|
||||
nonresidentNameTableEntries = nex.Model.NonResidentNameTable?
|
||||
.Select(nrnte => nrnte?.NameString == null ? string.Empty : Encoding.ASCII.GetString(nrnte.NameString))
|
||||
.Any(s => s.Contains("Rainbow Technologies Installation Program")) ?? false;
|
||||
if (nonresidentNameTableEntries)
|
||||
return "Rainbow Sentinel";
|
||||
|
||||
// Found in "WNCEDITD.EXE" and "WNCEDITO.EXE" in IA item "czchip199707cd".
|
||||
nonresidentNameTableEntries = nex.Model.NonResidentNameTable?
|
||||
.Select(nrnte => nrnte?.NameString == null ? string.Empty : Encoding.ASCII.GetString(nrnte.NameString))
|
||||
.Any(s => s.Contains("NetSentinel-C Editor for Windows")) ?? false;
|
||||
if (nonresidentNameTableEntries)
|
||||
return "NetSentinel-C Editor for Windows";
|
||||
|
||||
// TODO: Investigate "SentinelScribe Windows Driver DLL" found in "NKWIN.DLL" in IA item "czchip199707cd".
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public string? CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug)
|
||||
{
|
||||
@@ -33,30 +141,6 @@ namespace BinaryObjectScanner.Protection
|
||||
if (sections == null)
|
||||
return null;
|
||||
|
||||
// Get the .data/DATA section strings, if they exist
|
||||
var strs = pex.GetFirstSectionStrings(".data") ?? pex.GetFirstSectionStrings("DATA");
|
||||
if (strs != null)
|
||||
{
|
||||
// Found in "ADESKSYS.DLL"/"WINADMIN.EXE"/"WINQUERY.EXE" in BA entry "Autodesk AutoCAD LT 98 (1998) (CD) [English] [Dutch]", folder "\netsetup\SUPPORT\IPX".
|
||||
if (strs.Any(s => s.Contains("Rainbow SentinelSuperPro")))
|
||||
return "Rainbow Sentinel SuperPro";
|
||||
}
|
||||
|
||||
// Get the .text section strings, if they exist
|
||||
strs = pex.GetFirstSectionStrings(".text");
|
||||
if (strs != null)
|
||||
{
|
||||
// Found in "ACLT.HWL" in BA entry "Autodesk AutoCAD LT 98 (1998) (CD) [English] [Dutch]", folder "\aclt\DRV\W95LOCK".
|
||||
// Found in "ACAD.HWL" in BA entry "Autodesk AutoCAD r14 (1997)" and IA item "auto-cad-r14-cdrom".
|
||||
if (strs.Any(s => s.Contains("SENTINEL.VXD")))
|
||||
return "Rainbow Sentinel SuperPro";
|
||||
|
||||
// Found in "ADESKSYS.DLL" in BA entry "Autodesk AutoCAD LT 98 (1998) (CD) [English] [Dutch]", folder "\netsetup\SUPPORT\IPX".
|
||||
// TODO: Investigate "Elan License Manager" mentioned here.
|
||||
if (strs.Any(s => s.Contains("Rainbow SentinelSuperPro")))
|
||||
return "Rainbow Sentinel SuperPro";
|
||||
}
|
||||
|
||||
// TODO: Figure out why resources for "RNBOVTMP.DLL", "SENTTEMP.DLL", "SNTI386.DLL", and "SX32W.DL_"/"SX32W.DLL" aren't getting read properly, causing checks for these files to not work.
|
||||
|
||||
var name = pex.FileDescription;
|
||||
@@ -81,6 +165,19 @@ namespace BinaryObjectScanner.Protection
|
||||
if (name?.Equals("Rainbow Technologies SentinelSuperPro WIN32 DLL", StringComparison.OrdinalIgnoreCase) == true)
|
||||
return $"Rainbow Sentinel SuperPro {pex.ProductVersion}";
|
||||
|
||||
// Found in "SP32W.DLL" in IA item "pcwkcd-1296".
|
||||
if (name?.Equals("Rainbow Technologies SentinelPro WIN32 DLL", StringComparison.OrdinalIgnoreCase) == true)
|
||||
return $"Rainbow SentinelPro {pex.ProductVersion}";
|
||||
|
||||
// Found in "NSRVGX.EXE" in IA item "czchip199707cd".
|
||||
if (name?.Equals("NetSentinel Server for WIN 32", StringComparison.OrdinalIgnoreCase) == true)
|
||||
return "Rainbow NetSentinel Server for Win32";
|
||||
|
||||
// Found in "\disc4\cad\sdcc_200.zip\DISK1\_USER1.HDR\Language_Independent_Intel_32_Files\SNTNLUSB.SYS" 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".
|
||||
// TODO: Check if the version included with this is useful.
|
||||
if (name?.Equals("Rainbow Technologies Sentinel Device Driver", StringComparison.OrdinalIgnoreCase) == true)
|
||||
return "Rainbow Sentinel Driver";
|
||||
|
||||
name = pex.ProductName;
|
||||
|
||||
// Found in multiple files in BA entry "Autodesk AutoCAD LT 98 (1998) (CD) [English] [Dutch]", including "RNBOVTMP.DLL", "SENTTEMP.DLL", and "SNTI386.DLL".
|
||||
@@ -95,6 +192,98 @@ namespace BinaryObjectScanner.Protection
|
||||
if (name?.Equals("Rainbow Technologies SentinelSuperPro WIN32 DLL", StringComparison.OrdinalIgnoreCase) == true)
|
||||
return $"Rainbow Sentinel SuperPro {pex.ProductVersion}";
|
||||
|
||||
// Found in "SP32W.DLL" in IA item "pcwkcd-1296".
|
||||
if (name?.Equals("Rainbow Technologies SentinelPro WIN32 DLL", StringComparison.OrdinalIgnoreCase) == true)
|
||||
return $"Rainbow SentinelPro {pex.ProductVersion}";
|
||||
|
||||
// Found in "F481_SetupSysDriver.exe.B391C18A_6953_11D4_82CB_00D0B72E1DB9"/"SetupSysDriver.exe" in IA item "chip-cds-2001-08".
|
||||
if (name?.Equals("Sentinel System Driver", StringComparison.OrdinalIgnoreCase) == true)
|
||||
return $"Rainbow Sentinel {pex.ProductVersion}";
|
||||
|
||||
// Found in "\disc4\cad\sdcc_200.zip\DISK1\_USER1.HDR\Language_Independent_Intel_32_Files\SNTNLUSB.SYS" 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".
|
||||
// TODO: Check if the version included with this is useful.
|
||||
if (name?.Equals("Rainbow Technologies USB Security Device Driver", StringComparison.OrdinalIgnoreCase) == true)
|
||||
return "Rainbow Sentinel Driver";
|
||||
|
||||
// Get the .data/DATA section strings, if they exist
|
||||
var strs = pex.GetFirstSectionStrings(".data") ?? pex.GetFirstSectionStrings("DATA");
|
||||
if (strs != null)
|
||||
{
|
||||
// Found in "ADESKSYS.DLL"/"WINADMIN.EXE"/"WINQUERY.EXE" in BA entry "Autodesk AutoCAD LT 98 (1998) (CD) [English] [Dutch]", folder "\netsetup\SUPPORT\IPX".
|
||||
if (strs.Any(s => s.Contains("Rainbow SentinelSuperPro")))
|
||||
return "Rainbow Sentinel SuperPro";
|
||||
|
||||
// Found in "SETUPAXP.EXE", "SETUPMPS.EXE", and "SETUPPPC.EXE" in IA item "czchip199707cd".
|
||||
if (strs.Any(s => s.Contains("Sentinel Driver Setup Program")))
|
||||
return "Rainbow Sentinel";
|
||||
}
|
||||
|
||||
// Get the .rdata section strings, if they exist
|
||||
strs = pex.GetFirstSectionStrings(".rdata");
|
||||
if (strs != null)
|
||||
{
|
||||
// Found in "SP32W.DLL" in IA item "pcwkcd-1296".
|
||||
if (strs.Any(s => s.Contains("SentinelPro WIN32 DLL")))
|
||||
return "Rainbow SentinelPro";
|
||||
|
||||
// Found in "NKWIN32.DLL" in IA item "czchip199707cd".
|
||||
if (strs.Any(s => s.Contains("NetSentinel-C Windows NT Driver DLL")))
|
||||
return "Rainbow NetSentinel-C Windows NT Driver";
|
||||
|
||||
// Found in "NSLMS32.DLL" in IA item "czchip199707cd".
|
||||
if (strs.Any(s => s.Contains("NetSentinel 32-Bit Windows DLL")))
|
||||
return "Rainbow NetSentinel Win32 Driver";
|
||||
|
||||
// Found in "W32EDITD.EXE" and "W32EDITO.EXE" in IA item "czchip199707cd".
|
||||
if (strs.Any(s => s.Contains("NetSentinel-C Editor for Windows")))
|
||||
return "NetSentinel-C Editor for Win32";
|
||||
|
||||
// Generic case to catch undetected versions.
|
||||
if (strs.Any(s => s.Contains("SentinelPro")))
|
||||
return "Rainbow SentinelPro (Unknown Version - Please report to us on GitHub)";
|
||||
}
|
||||
|
||||
// Get the .rsrc section strings, if they exist
|
||||
strs = pex.GetFirstSectionStrings(".rsrc");
|
||||
if (strs != null)
|
||||
{
|
||||
// Found in "WINMON.exe" in IA item "czchip199707cd".
|
||||
if (strs.Any(s => s.Contains("NetSentinel Monitor")))
|
||||
return "Rainbow NetSentinel Monitor";
|
||||
}
|
||||
|
||||
// Get the .text section strings, if they exist
|
||||
strs = pex.GetFirstSectionStrings(".text");
|
||||
if (strs != null)
|
||||
{
|
||||
// Found in "ACLT.HWL" in BA entry "Autodesk AutoCAD LT 98 (1998) (CD) [English] [Dutch]", folder "\aclt\DRV\W95LOCK".
|
||||
// Found in "ACAD.HWL" in BA entry "Autodesk AutoCAD r14 (1997)" and IA item "auto-cad-r14-cdrom".
|
||||
if (strs.Any(s => s.Contains("\\\\.\\SENTINEL.VXD")))
|
||||
return "Rainbow Sentinel";
|
||||
|
||||
// Found in "ADESKSYS.DLL" in BA entry "Autodesk AutoCAD LT 98 (1998) (CD) [English] [Dutch]", folder "\netsetup\SUPPORT\IPX".
|
||||
// TODO: Investigate "Elan License Manager" mentioned here.
|
||||
if (strs.Any(s => s.Contains("Rainbow SentinelSuperPro")))
|
||||
return "Rainbow Sentinel SuperPro";
|
||||
|
||||
// Found in "F1321_dorapro.exe" in IA item "chip-cds-2001-08".
|
||||
if (strs.Any(s => s.Contains("modSentinelSuperPro")))
|
||||
return "Rainbow Sentinel SuperPro";
|
||||
|
||||
// Found in "F1321_dorapro.exe" in IA item "chip-cds-2001-08".
|
||||
if (strs.Any(s => s.Contains("clsSentinelSuperPro")))
|
||||
return "Rainbow Sentinel SuperPro";
|
||||
|
||||
// Found in "SENTSTRT.EXE" in IA item "czchip199707cd".
|
||||
if (strs.Any(s => s.Contains("Sentinel Driver Startup Program")))
|
||||
return "Rainbow Sentinel";
|
||||
|
||||
// Found in "SETUPX86.EXE" in IA item "czchip199707cd".
|
||||
if (strs.Any(s => s.Contains("Sentinel Windows NT Driver Setup")))
|
||||
return "Rainbow Sentinel";
|
||||
}
|
||||
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -107,8 +296,11 @@ namespace BinaryObjectScanner.Protection
|
||||
{
|
||||
var matchers = new List<PathMatchSet>
|
||||
{
|
||||
// The Parallel Port driver for Rainbow Sentinel on Win9x (https://www.rainbow.com.my/document/endusertroubleshooting.pdf).
|
||||
// Unfortunately, the file name overlaps with a file used by Clam Sentinel (https://clamsentinel.sourceforge.net/).
|
||||
// new(new FilePathMatch("SENTINEL.VXD"), "Rainbow Sentinel"),
|
||||
|
||||
// Found in BA entry "Autodesk AutoCAD LT 98 (1998) (CD) [English] [Dutch]" and IA item "auto-cad-r14-cdrom".
|
||||
new(new FilePathMatch("SENTINEL.VXD"), "Rainbow Sentinel"),
|
||||
new(new FilePathMatch("SENTSTRT.EXE"), "Rainbow Sentinel"),
|
||||
new(new FilePathMatch("SENTW95.DLL"), "Rainbow Sentinel"),
|
||||
new(new FilePathMatch("SENTW95.EXE"), "Rainbow Sentinel"),
|
||||
@@ -127,9 +319,78 @@ namespace BinaryObjectScanner.Protection
|
||||
new(new FilePathMatch("RAINBNT.Z"), "Rainbow Sentinel"),
|
||||
|
||||
// Found in "wd126.zip/WDSHARE.EXE" in IA item "ASMEsMechanicalEngineeringToolkit1997December" and "WDSHARE.ZIP/WDSHARE.EXE/SX32W.DL_" in IA item "aplicaciones-windows".
|
||||
new(new FilePathMatch("RainbowSentinel.386"), "Rainbow Sentinel"),
|
||||
new(new FilePathMatch("SX32W.DL_"), "Rainbow Sentinel"),
|
||||
new(new FilePathMatch("SX32W.DLL"), "Rainbow Sentinel"),
|
||||
new(new FilePathMatch("RainbowSentinel.386"), "Rainbow Sentinel"),
|
||||
new(new FilePathMatch("SX32W.DL_"), "Rainbow Sentinel"),
|
||||
new(new FilePathMatch("SX32W.DLL"), "Rainbow Sentinel"),
|
||||
|
||||
// Found in IA item "pcwkcd-1296".
|
||||
new(new FilePathMatch("SP32W.DLL"), "Rainbow Sentinel"),
|
||||
new(new FilePathMatch("SSWIN.DLL"), "Rainbow Sentinel"),
|
||||
|
||||
// Found in IA item "czchip199707cd".
|
||||
new(new FilePathMatch("SENTINEL.DPP"), "Rainbow Sentinel OS/2 Installation Script"),
|
||||
new(new FilePathMatch("SENTDOS.SYS"), "Rainbow Sentinel DOS Driver"),
|
||||
new(new FilePathMatch("SENTINEL.386"), "Rainbow Sentinel Windows 3.1 Driver"),
|
||||
new(new FilePathMatch("SNTALPHA.DLL"), "Rainbow Sentinel Windows NT Alpha Platform Driver"),
|
||||
new(new FilePathMatch("SNTI386.DLL"), "Rainbow Sentinel Windows NT Intel Platform Driver"),
|
||||
new(new FilePathMatch("SNTMIPS.DLL"), "Rainbow Sentinel Windows NT MIPS Platform Driver"),
|
||||
new(new FilePathMatch("SNTPPC.DLL"), "Rainbow Sentinel Windows NT PowerPC Platform Driver"),
|
||||
new(new FilePathMatch("NSRVDI.EXE"), "Rainbow NetSentinel Server for DOS"),
|
||||
new(new FilePathMatch("NSRVDN.EXE"), "Rainbow NetSentinel Server for DOS"),
|
||||
new(new FilePathMatch("NSRVNI.NLM"), "Rainbow NetSentinel Server for Novell NetWare"),
|
||||
new(new FilePathMatch("NSRVOM.EXE"), "Rainbow NetSentinel Server for OS/2"),
|
||||
new(new FilePathMatch("NSRVGX.EXE"), "Rainbow NetSentinel Server for Win32"),
|
||||
|
||||
// Found in "\disc4\cad\sdcc_200.zip\DISK1\_USER1.HDR\Language_Independent_Intel_32_Files" 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".
|
||||
// TODO: Add text file checks for these IFX files.
|
||||
new(new FilePathMatch("SNTNLUSB.IFX"), "Rainbow Sentinel USB Driver"),
|
||||
new(new FilePathMatch("SNTNLUSB.INF"), "Rainbow Sentinel USB Driver"),
|
||||
new(new FilePathMatch("SNTNLUSB.SYS"), "Rainbow Sentinel USB Driver"),
|
||||
new(new FilePathMatch("SNTUSB95.IFX"), "Rainbow Sentinel USB Driver"),
|
||||
new(new FilePathMatch("SNTUSB95.INF"), "Rainbow Sentinel USB Driver"),
|
||||
new(new FilePathMatch("SNTUSB95.SYS"), "Rainbow Sentinel USB Driver"),
|
||||
|
||||
// Found in IA item "czchip199707cd".
|
||||
new(new List<PathMatch>
|
||||
{
|
||||
new FilePathMatch("DOSMON.EXE"),
|
||||
new FilePathMatch("FIND.EXE"),
|
||||
new FilePathMatch("NCEDIT.EXE"),
|
||||
new FilePathMatch("NETEVAL.EXE"),
|
||||
}, "Rainbow NetSentinel Monitor for DOS"),
|
||||
|
||||
// Found in IA item "czchip199707cd".
|
||||
new(new List<PathMatch>
|
||||
{
|
||||
new FilePathMatch("OS2MON.EXE"),
|
||||
new FilePathMatch("RHPANELP.DLL"),
|
||||
}, "Rainbow NetSentinel Monitor for OS/2"),
|
||||
|
||||
// Found in IA item "czchip199707cd".
|
||||
new(new List<PathMatch>
|
||||
{
|
||||
new FilePathMatch("MAPFILE.TXT"),
|
||||
new FilePathMatch("NKWIN32.DLL"),
|
||||
new FilePathMatch("NSLMS32.DLL"),
|
||||
new FilePathMatch("W32EDITD.EXE"),
|
||||
new FilePathMatch("W32EDITO.EXE"),
|
||||
new FilePathMatch("WINMON.DOC"),
|
||||
new FilePathMatch("WINMON.EXE"),
|
||||
new FilePathMatch("WINMON.HLP"),
|
||||
new FilePathMatch("WMON_DOC.EXE"),
|
||||
}, "Rainbow NetSentinel Monitor for Win32"),
|
||||
|
||||
// Found in IA item "chip-cds-2001-08".
|
||||
// File names for Rainbow Sentinel files sometimes found in ".cab" files.
|
||||
new(new FilePathMatch("F194_rnbovdd.dll.B391C188_6953_11D4_82CB_00D0B72E1DB9"), "Rainbow Sentinel"),
|
||||
new(new FilePathMatch("F195_sentinel.sys.B391C188_6953_11D4_82CB_00D0B72E1DB9"), "Rainbow Sentinel"),
|
||||
new(new FilePathMatch("F225_sentinel.hlp.B391C18A_6953_11D4_82CB_00D0B72E1DB9"), "Rainbow Sentinel"),
|
||||
new(new FilePathMatch("F227_snti386.dll.B391C18A_6953_11D4_82CB_00D0B72E1DB9"), "Rainbow Sentinel"),
|
||||
new(new FilePathMatch("F288_sentinel.vxd.B391C188_6953_11D4_82CB_00D0B72E1DB9"), "Rainbow Sentinel"),
|
||||
new(new FilePathMatch("F317_sentstrt.exe.B391C188_6953_11D4_82CB_00D0B72E1DB9"), "Rainbow Sentinel"),
|
||||
new(new FilePathMatch("F344_sentw9x.hlp.B391C18A_6953_11D4_82CB_00D0B72E1DB9"), "Rainbow Sentinel"),
|
||||
new(new FilePathMatch("F481_SetupSysDriver.exe.B391C18A_6953_11D4_82CB_00D0B72E1DB9"), "Rainbow Sentinel"),
|
||||
new(new FilePathMatch("F766_SentinelDriverInstall_Start.htm.B391C18A_6953_11D4_82CB_00D0B72E1DB9"), "Rainbow Sentinel"),
|
||||
};
|
||||
|
||||
return MatchUtil.GetAllMatches(files, matchers, any: true);
|
||||
@@ -140,8 +401,12 @@ namespace BinaryObjectScanner.Protection
|
||||
{
|
||||
var matchers = new List<PathMatchSet>
|
||||
{
|
||||
// The Parallel Port driver for Rainbow Sentinel (https://www.rainbow.com.my/document/endusertroubleshooting.pdf).
|
||||
// Unforutnately, the file name overlaps with a file used by Clam Sentinel (https://clamsentinel.sourceforge.net/).
|
||||
// TODO: Add LE check for "SENTINEL.VXD" once LE checks are implemented.
|
||||
// new(new FilePathMatch("SENTINEL.VXD"), "Rainbow Sentinel"),
|
||||
|
||||
// Found in BA entry "Autodesk AutoCAD LT 98 (1998) (CD) [English] [Dutch]" and IA item "auto-cad-r14-cdrom".
|
||||
new(new FilePathMatch("SENTINEL.VXD"), "Rainbow Sentinel"),
|
||||
new(new FilePathMatch("SENTSTRT.EXE"), "Rainbow Sentinel"),
|
||||
new(new FilePathMatch("SENTW95.DLL"), "Rainbow Sentinel"),
|
||||
new(new FilePathMatch("SENTW95.EXE"), "Rainbow Sentinel"),
|
||||
@@ -163,6 +428,40 @@ namespace BinaryObjectScanner.Protection
|
||||
new(new FilePathMatch("RainbowSentinel.386"), "Rainbow Sentinel"),
|
||||
new(new FilePathMatch("SX32W.DL_"), "Rainbow Sentinel"),
|
||||
new(new FilePathMatch("SX32W.DLL"), "Rainbow Sentinel"),
|
||||
|
||||
// Found in IA item "pcwkcd-1296".
|
||||
new(new FilePathMatch("SP32W.DLL"), "Rainbow Sentinel"),
|
||||
new(new FilePathMatch("SSWIN.DLL"), "Rainbow Sentinel"),
|
||||
|
||||
// Found in IA item "czchip199707cd".
|
||||
new(new FilePathMatch("SENTINEL.DPP"), "Rainbow Sentinel OS/2 Installation Script"),
|
||||
new(new FilePathMatch("SENTDOS.SYS"), "Rainbow Sentinel DOS Driver"),
|
||||
new(new FilePathMatch("SENTINEL.386"), "Rainbow Sentinel Windows 3.1 Driver"),
|
||||
new(new FilePathMatch("SNTALPHA.DLL"), "Rainbow Sentinel Windows NT Alpha Platform Driver"),
|
||||
new(new FilePathMatch("SNTI386.DLL"), "Rainbow Sentinel Windows NT Intel Platform Driver"),
|
||||
new(new FilePathMatch("SNTMIPS.DLL"), "Rainbow Sentinel Windows NT MIPS Platform Driver"),
|
||||
new(new FilePathMatch("SNTPPC.DLL"), "Rainbow Sentinel Windows NT PowerPC Platform Driver"),
|
||||
|
||||
// Found in "\disc4\cad\sdcc_200.zip\DISK1\_USER1.HDR\Language_Independent_Intel_32_Files" 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".
|
||||
// TODO: Add text file checks for these IFX files.
|
||||
new(new FilePathMatch("SNTNLUSB.IFX"), "Rainbow Sentinel USB Driver"),
|
||||
new(new FilePathMatch("SNTNLUSB.INF"), "Rainbow Sentinel USB Driver"),
|
||||
new(new FilePathMatch("SNTNLUSB.SYS"), "Rainbow Sentinel USB Driver"),
|
||||
new(new FilePathMatch("SNTUSB95.IFX"), "Rainbow Sentinel USB Driver"),
|
||||
new(new FilePathMatch("SNTUSB95.INF"), "Rainbow Sentinel USB Driver"),
|
||||
new(new FilePathMatch("SNTUSB95.SYS"), "Rainbow Sentinel USB Driver"),
|
||||
|
||||
// Found in IA item "chip-cds-2001-08".
|
||||
// File names for Rainbow Sentinel files sometimes found in ".cab" files.
|
||||
new(new FilePathMatch("F194_rnbovdd.dll.B391C188_6953_11D4_82CB_00D0B72E1DB9"), "Rainbow Sentinel"),
|
||||
new(new FilePathMatch("F195_sentinel.sys.B391C188_6953_11D4_82CB_00D0B72E1DB9"), "Rainbow Sentinel"),
|
||||
new(new FilePathMatch("F225_sentinel.hlp.B391C18A_6953_11D4_82CB_00D0B72E1DB9"), "Rainbow Sentinel"),
|
||||
new(new FilePathMatch("F227_snti386.dll.B391C18A_6953_11D4_82CB_00D0B72E1DB9"), "Rainbow Sentinel"),
|
||||
new(new FilePathMatch("F288_sentinel.vxd.B391C188_6953_11D4_82CB_00D0B72E1DB9"), "Rainbow Sentinel"),
|
||||
new(new FilePathMatch("F317_sentstrt.exe.B391C188_6953_11D4_82CB_00D0B72E1DB9"), "Rainbow Sentinel"),
|
||||
new(new FilePathMatch("F344_sentw9x.hlp.B391C18A_6953_11D4_82CB_00D0B72E1DB9"), "Rainbow Sentinel"),
|
||||
new(new FilePathMatch("F481_SetupSysDriver.exe.B391C18A_6953_11D4_82CB_00D0B72E1DB9"), "Rainbow Sentinel"),
|
||||
new(new FilePathMatch("F766_SentinelDriverInstall_Start.htm.B391C18A_6953_11D4_82CB_00D0B72E1DB9"), "Rainbow Sentinel"),
|
||||
};
|
||||
|
||||
return MatchUtil.GetFirstMatch(path, matchers, any: true);
|
||||
|
||||
75
BinaryObjectScanner/Protection/RealArcade.cs
Normal file
75
BinaryObjectScanner/Protection/RealArcade.cs
Normal file
@@ -0,0 +1,75 @@
|
||||
using System;
|
||||
#if NET40_OR_GREATER || NETCOREAPP
|
||||
using System.Collections.Concurrent;
|
||||
#endif
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using BinaryObjectScanner.Interfaces;
|
||||
using SabreTools.Matching;
|
||||
using SabreTools.Serialization.Wrappers;
|
||||
|
||||
namespace BinaryObjectScanner.Protection
|
||||
{
|
||||
/// <summary>
|
||||
/// RealArcade was a game platform that allowed users to play timed demos of games, and then prompted them to purchase the game in order to play the game without a limit.
|
||||
/// Although the servers are long dead, there is a community project actively being developed to allow users to properly download and play these games.
|
||||
/// Links:
|
||||
/// https://github.com/lightbulbatelier/RealArcade-DGA
|
||||
/// https://archive.org/details/realrcade-games-preservation-project
|
||||
/// </summary>
|
||||
public class RealArcade : IPathCheck, 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 .data section strings, if they exist
|
||||
var strs = pex.GetFirstSectionStrings(".data");
|
||||
if (strs != null)
|
||||
{
|
||||
// Found in "rebound.exe" in the installation directory for "Rebound" in IA item "Nova_RealArcadeCD_USA".
|
||||
if (strs.Any(s => s.Contains("RngInterstitialDLL")))
|
||||
return "RealArcade";
|
||||
}
|
||||
|
||||
// Found in "RngInterstitial.dll" in the RealArcade installation directory in IA item "Nova_RealArcadeCD_USA".
|
||||
var name = pex.FileDescription;
|
||||
if (name?.Contains("RngInterstitial") == true)
|
||||
return "RealArcade";
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
#if NET20 || NET35
|
||||
public Queue<string> CheckDirectoryPath(string path, IEnumerable<string>? files)
|
||||
#else
|
||||
public ConcurrentQueue<string> CheckDirectoryPath(string path, IEnumerable<string>? files)
|
||||
#endif
|
||||
{
|
||||
var matchers = new List<PathMatchSet>
|
||||
{
|
||||
// ".rgs" and ".mez" files are also associated with RealArcade.
|
||||
new(new FilePathMatch("RngInterstitial.dll"), "RealArcade"),
|
||||
};
|
||||
|
||||
return MatchUtil.GetAllMatches(files, matchers, any: true);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public string? CheckFilePath(string path)
|
||||
{
|
||||
var matchers = new List<PathMatchSet>
|
||||
{
|
||||
// ".rgs" and ".mez" files are also associated with RealArcade.
|
||||
new(new FilePathMatch("RngInterstitial.dll"), "RealArcade"),
|
||||
};
|
||||
|
||||
return MatchUtil.GetFirstMatch(path, matchers, any: true);
|
||||
}
|
||||
}
|
||||
}
|
||||
84
BinaryObjectScanner/Protection/Roxxe.cs
Normal file
84
BinaryObjectScanner/Protection/Roxxe.cs
Normal file
@@ -0,0 +1,84 @@
|
||||
using System;
|
||||
#if NET40_OR_GREATER || NETCOREAPP
|
||||
using System.Collections.Concurrent;
|
||||
#endif
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using BinaryObjectScanner.Interfaces;
|
||||
using SabreTools.Matching;
|
||||
using SabreTools.Serialization.Wrappers;
|
||||
|
||||
namespace BinaryObjectScanner.Protection
|
||||
{
|
||||
/// <summary>
|
||||
/// Roxxe was a Czech DRM. It appears to have been a simple disc check that also relied on unusual disc manufacturing and dummy files to attempt to prevent copying.
|
||||
///
|
||||
/// DRML: https://github.com/TheRogueArchivist/DRML/blob/main/entries/Roxxe/Roxxe.md
|
||||
/// </summary>
|
||||
public class Roxxe : IPathCheck, 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 code/CODE section strings, if they exist
|
||||
var strs = pex.GetFirstSectionStrings("code") ?? pex.GetFirstSectionStrings("CODE");
|
||||
if (strs != null)
|
||||
{
|
||||
// Found in "Owar.exe" in IA item "game4u-22-cd".
|
||||
if (strs.Any(s => s.Contains("TRCHANGER.INI")))
|
||||
return "Roxxe";
|
||||
}
|
||||
|
||||
// Get the .rsrc section strings, if they exist
|
||||
// TODO: Check for these strings specifically within the application-defined resource that they're found in, not just the generic resource section.
|
||||
strs = pex.GetFirstSectionStrings(".rsrc");
|
||||
if (strs != null)
|
||||
{
|
||||
// Found in "Owar.exe" in IA items "game4u-22-cd" and "original-war".
|
||||
// These checks are less reliable, as they are still found in a version of the game that appears to have patched out Roxxe (the version present in IA item "original-war").
|
||||
if (strs.Any(s => s.Contains("PRRT01")))
|
||||
return "Roxxe (Possibly remnants)";
|
||||
|
||||
if (strs.Any(s => s.Contains("CommonPRRT")))
|
||||
return "Roxxe (Possibly remnants)";
|
||||
|
||||
// Currently overmatches, will likely be a viable check when better Delphi executable parsing is available.
|
||||
// if (strs.Any(s => s.Contains("roxe")))
|
||||
// return "Roxxe (Possibly remnants)";
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
#if NET20 || NET35
|
||||
public Queue<string> CheckDirectoryPath(string path, IEnumerable<string>? files)
|
||||
#else
|
||||
public ConcurrentQueue<string> CheckDirectoryPath(string path, IEnumerable<string>? files)
|
||||
#endif
|
||||
{
|
||||
var matchers = new List<PathMatchSet>
|
||||
{
|
||||
// Files such as "TRCHANGER.INI" may be present, but haven't been found yet.
|
||||
};
|
||||
|
||||
return MatchUtil.GetAllMatches(files, matchers, any: true);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public string? CheckFilePath(string path)
|
||||
{
|
||||
var matchers = new List<PathMatchSet>
|
||||
{
|
||||
// Files such as "TRCHANGER.INI" may be present, but haven't been found yet.
|
||||
};
|
||||
|
||||
return MatchUtil.GetFirstMatch(path, matchers, any: true);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -226,31 +226,40 @@ namespace BinaryObjectScanner.Protection
|
||||
// These live in the MS-DOS stub, for some reason
|
||||
private static string GetV7Version(PortableExecutable pex)
|
||||
{
|
||||
int index = 172; // 64 bytes for DOS stub, 236 bytes in total
|
||||
try
|
||||
{
|
||||
int index = 172; // 64 bytes for DOS stub, 236 bytes in total
|
||||
#if NETFRAMEWORK
|
||||
byte[] bytes = new byte[4];
|
||||
Array.Copy(pex.StubExecutableData, index, bytes, 0, 4);
|
||||
byte[] bytes = new byte[4];
|
||||
Array.Copy(pex.StubExecutableData, index, bytes, 0, 4);
|
||||
#else
|
||||
byte[] bytes = new ReadOnlySpan<byte>(pex.StubExecutableData, index, 4).ToArray();
|
||||
byte[] bytes = new ReadOnlySpan<byte>(pex.StubExecutableData, index, 4).ToArray();
|
||||
#endif
|
||||
|
||||
//SecuROM 7 new and 8
|
||||
if (bytes[3] == 0x5C) // if (bytes[0] == 0xED && bytes[3] == 0x5C {
|
||||
{
|
||||
return $"{bytes[0] ^ 0xEA}.{bytes[1] ^ 0x2C:00}.{bytes[2] ^ 0x8:0000}";
|
||||
//SecuROM 7 new and 8
|
||||
if (bytes[3] == 0x5C) // if (bytes[0] == 0xED && bytes[3] == 0x5C {
|
||||
{
|
||||
return $"{bytes[0] ^ 0xEA}.{bytes[1] ^ 0x2C:00}.{bytes[2] ^ 0x8:0000}";
|
||||
}
|
||||
|
||||
// SecuROM 7 old
|
||||
else
|
||||
{
|
||||
index = 58; // 64 bytes for DOS stub, 122 bytes in total
|
||||
#if NETFRAMEWORK
|
||||
bytes = new byte[2];
|
||||
Array.Copy(pex.StubExecutableData, index, bytes, 0, 2);
|
||||
#else
|
||||
bytes = new ReadOnlySpan<byte>(pex.StubExecutableData, index, 2).ToArray();
|
||||
#endif
|
||||
return $"7.{bytes[0] ^ 0x10:00}.{bytes[1] ^ 0x10:0000}"; //return "7.01-7.10"
|
||||
}
|
||||
}
|
||||
|
||||
// SecuROM 7 old
|
||||
else
|
||||
catch (ArgumentException)
|
||||
{
|
||||
index = 58; // 64 bytes for DOS stub, 122 bytes in total
|
||||
#if NETFRAMEWORK
|
||||
bytes = new byte[2];
|
||||
Array.Copy(pex.StubExecutableData, index, bytes, 0, 2);
|
||||
#else
|
||||
bytes = new ReadOnlySpan<byte>(pex.StubExecutableData, index, 2).ToArray();
|
||||
#endif
|
||||
return $"7.{bytes[0] ^ 0x10:00}.{bytes[1] ^ 0x10:0000}"; //return "7.01-7.10"
|
||||
// If SecuROM is stripped, the MS-DOS stub might be shorter.
|
||||
// We then know that SecuROM -was- there, but we don't know what exact version.
|
||||
return "7 remnants";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -27,7 +27,35 @@ namespace BinaryObjectScanner.Protection
|
||||
if (sections == null)
|
||||
return null;
|
||||
|
||||
var name = pex.LegalCopyright;
|
||||
// TODO: Find what fvinfo field actually maps to this
|
||||
var name = pex.FileDescription;
|
||||
|
||||
// There are some File Description checks that are currently too generic to use.
|
||||
// "Host Library" - Found in "protect.dll" in Redump entry 81756.
|
||||
// "User Interface Application" - Found in "protect.exe" in Redump entry 81756.
|
||||
// "Helper Application" - Found in "protect.x64" and "protect.x86" in Redump entry 81756.
|
||||
|
||||
// Found in "sfdrvrem.exe" in Redump entry 102677.
|
||||
if (name?.Contains("FrontLine Drivers Removal Tool") == true)
|
||||
return $"StarForce FrontLine Driver Removal Tool";
|
||||
|
||||
// Found in "protect.exe" in Redump entry 94805.
|
||||
if (name?.Contains("FrontLine Protection GUI Application") == true)
|
||||
return $"StarForce {pex.GetInternalVersion()}";
|
||||
|
||||
// Found in "protect.dll" in Redump entry 94805.
|
||||
if (name?.Contains("FrontLine Protection Library") == true)
|
||||
return $"StarForce {pex.GetInternalVersion()}";
|
||||
|
||||
// Found in "protect.x64" and "protect.x86" in Redump entry 94805.
|
||||
if (name?.Contains("FrontLine Helper") == true)
|
||||
return $"StarForce {pex.GetInternalVersion()}";
|
||||
|
||||
// TODO: Find a sample of this check.
|
||||
if (name?.Contains("Protected Module") == true)
|
||||
return $"StarForce 5";
|
||||
|
||||
name = pex.LegalCopyright;
|
||||
if (name?.StartsWith("(c) Protection Technology") == true) // (c) Protection Technology (StarForce)?
|
||||
return $"StarForce {pex.GetInternalVersion()}";
|
||||
else if (name?.Contains("Protection Technology") == true) // Protection Technology (StarForce)?
|
||||
@@ -61,30 +89,6 @@ namespace BinaryObjectScanner.Protection
|
||||
return $"StarForce {pex.GetInternalVersion()}";
|
||||
}
|
||||
|
||||
// TODO: Find what fvinfo field actually maps to this
|
||||
name = pex.FileDescription;
|
||||
|
||||
// There are some File Description checks that are currently too generic to use.
|
||||
// "Host Library" - Found in "protect.dll" in Redump entry 81756.
|
||||
// "User Interface Application" - Found in "protect.exe" in Redump entry 81756.
|
||||
// "Helper Application" - Found in "protect.x64" and "protect.x86" in Redump entry 81756.
|
||||
|
||||
// Found in "protect.exe" in Redump entry 94805.
|
||||
if (name?.Contains("FrontLine Protection GUI Application") == true)
|
||||
return $"StarForce {pex.GetInternalVersion()}";
|
||||
|
||||
// Found in "protect.dll" in Redump entry 94805.
|
||||
if (name?.Contains("FrontLine Protection Library") == true)
|
||||
return $"StarForce {pex.GetInternalVersion()}";
|
||||
|
||||
// Found in "protect.x64" and "protect.x86" in Redump entry 94805.
|
||||
if (name?.Contains("FrontLine Helper") == true)
|
||||
return $"StarForce {pex.GetInternalVersion()}";
|
||||
|
||||
// TODO: Find a sample of this check.
|
||||
if (name?.Contains("Protected Module") == true)
|
||||
return $"StarForce 5";
|
||||
|
||||
// TODO: Check to see if there are any missing checks
|
||||
// https://github.com/horsicq/Detect-It-Easy/blob/master/db/PE/StarForce.2.sg
|
||||
|
||||
|
||||
@@ -55,7 +55,8 @@ namespace BinaryObjectScanner.Protection
|
||||
new(new List<PathMatch>
|
||||
{
|
||||
// TODO: Identify based on "Steam(TM)" being present in "Description" but not in "File Description".
|
||||
new FilePathMatch("steam.exe"),
|
||||
// Overmatches on some files, such as IA item "ASMEsMechanicalEngineeringToolkit1997December".
|
||||
// new FilePathMatch("steam.exe"),
|
||||
|
||||
new FilePathMatch("steam.ini"),
|
||||
|
||||
|
||||
@@ -5,11 +5,14 @@ using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
#if NET462_OR_GREATER || NETCOREAPP
|
||||
using System.Text;
|
||||
#endif
|
||||
using System.Threading.Tasks;
|
||||
using BinaryObjectScanner.FileType;
|
||||
using BinaryObjectScanner.Interfaces;
|
||||
using BinaryObjectScanner.Utilities;
|
||||
using SabreTools.IO.Extensions;
|
||||
using SabreTools.Serialization.Wrappers;
|
||||
using static BinaryObjectScanner.Utilities.Dictionary;
|
||||
|
||||
@@ -92,7 +95,7 @@ namespace BinaryObjectScanner
|
||||
public ConcurrentDictionary<string, ConcurrentQueue<string>>? GetProtections(string path)
|
||||
#endif
|
||||
{
|
||||
return GetProtections(new List<string> { path });
|
||||
return GetProtections([path]);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -131,11 +134,7 @@ namespace BinaryObjectScanner
|
||||
if (Directory.Exists(path))
|
||||
{
|
||||
// Enumerate all files at first for easier access
|
||||
#if NET20 || NET35
|
||||
var files = Directory.GetFiles(path, "*", SearchOption.AllDirectories).ToList();
|
||||
#else
|
||||
var files = Directory.EnumerateFiles(path, "*", SearchOption.AllDirectories).ToList();
|
||||
#endif
|
||||
var files = IOExtensions.SafeEnumerateFiles(path, "*", SearchOption.AllDirectories).ToList();
|
||||
|
||||
// Scan for path-detectable protections
|
||||
if (ScanPaths)
|
||||
@@ -328,12 +327,12 @@ namespace BinaryObjectScanner
|
||||
}
|
||||
|
||||
// Get the file type either from magic number or extension
|
||||
SupportedFileType fileType = FileTypes.GetFileType(magic);
|
||||
if (fileType == SupportedFileType.UNKNOWN)
|
||||
fileType = FileTypes.GetFileType(extension);
|
||||
WrapperType fileType = WrapperFactory.GetFileType(magic);
|
||||
if (fileType == WrapperType.UNKNOWN)
|
||||
fileType = WrapperFactory.GetFileType(extension);
|
||||
|
||||
// If we still got unknown, just return null
|
||||
if (fileType == SupportedFileType.UNKNOWN)
|
||||
if (fileType == WrapperType.UNKNOWN)
|
||||
return null;
|
||||
|
||||
#region Non-Archive File Types
|
||||
@@ -457,7 +456,7 @@ namespace BinaryObjectScanner
|
||||
AppendToDictionary(protections, fileName, subProtections.Values.ToArray());
|
||||
|
||||
// If we have any extractable packers
|
||||
var extractedProtections = HandleExtractableProtections(subProtections.Keys, fileName, stream);
|
||||
var extractedProtections = HandleExtractableProtections(subProtections.Keys, fileName, mz);
|
||||
if (extractedProtections != null)
|
||||
AppendToDictionary(protections, extractedProtections);
|
||||
}
|
||||
@@ -471,7 +470,7 @@ namespace BinaryObjectScanner
|
||||
AppendToDictionary(protections, fileName, subProtections.Values.ToArray());
|
||||
|
||||
// If we have any extractable packers
|
||||
var extractedProtections = HandleExtractableProtections(subProtections.Keys, fileName, stream);
|
||||
var extractedProtections = HandleExtractableProtections(subProtections.Keys, fileName, lex);
|
||||
if (extractedProtections != null)
|
||||
AppendToDictionary(protections, extractedProtections);
|
||||
}
|
||||
@@ -485,7 +484,7 @@ namespace BinaryObjectScanner
|
||||
AppendToDictionary(protections, fileName, subProtections.Values.ToArray());
|
||||
|
||||
// If we have any extractable packers
|
||||
var extractedProtections = HandleExtractableProtections(subProtections.Keys, fileName, stream);
|
||||
var extractedProtections = HandleExtractableProtections(subProtections.Keys, fileName, nex);
|
||||
if (extractedProtections != null)
|
||||
AppendToDictionary(protections, extractedProtections);
|
||||
}
|
||||
@@ -499,7 +498,7 @@ namespace BinaryObjectScanner
|
||||
AppendToDictionary(protections, fileName, subProtections.Values.ToArray());
|
||||
|
||||
// If we have any extractable packers
|
||||
var extractedProtections = HandleExtractableProtections(subProtections.Keys, fileName, stream);
|
||||
var extractedProtections = HandleExtractableProtections(subProtections.Keys, fileName, pex);
|
||||
if (extractedProtections != null)
|
||||
AppendToDictionary(protections, extractedProtections);
|
||||
}
|
||||
@@ -512,12 +511,12 @@ namespace BinaryObjectScanner
|
||||
/// </summary>
|
||||
/// <param name="classes">Set of classes returned from Exectuable scans</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="mz">MSDOS to scan the contents of</param>
|
||||
/// <returns>Set of protections found from extraction, null on error</returns>
|
||||
#if NET20 || NET35
|
||||
private Dictionary<string, Queue<string>>? HandleExtractableProtections<T>(Dictionary<T, string>.KeyCollection? classes, string fileName, Stream stream)
|
||||
private Dictionary<string, Queue<string>>? HandleExtractableProtections<T>(Dictionary<T, string>.KeyCollection? classes, string fileName, MSDOS mz)
|
||||
#else
|
||||
private ConcurrentDictionary<string, ConcurrentQueue<string>>? HandleExtractableProtections(IEnumerable<object>? classes, string fileName, Stream stream)
|
||||
private ConcurrentDictionary<string, ConcurrentQueue<string>>? HandleExtractableProtections(IEnumerable<object>? classes, string fileName, MSDOS mz)
|
||||
#endif
|
||||
{
|
||||
// If we have an invalid set of classes
|
||||
@@ -532,7 +531,7 @@ namespace BinaryObjectScanner
|
||||
#endif
|
||||
|
||||
// If we have any extractable packers
|
||||
var extractables = classes.Where(c => c is IExtractable).Select(c => c as IExtractable);
|
||||
var extractables = classes.Where(c => c is IExtractableMSDOSExecutable).Select(c => c as IExtractableMSDOSExecutable);
|
||||
#if NET20 || NET35
|
||||
foreach (var extractable in extractables)
|
||||
#else
|
||||
@@ -548,7 +547,166 @@ namespace BinaryObjectScanner
|
||||
#endif
|
||||
|
||||
// Get the protection for the class, if possible
|
||||
var extractedProtections = Handler.HandleExtractable(extractable, fileName, stream, this);
|
||||
var extractedProtections = Handler.HandleExtractable(extractable, fileName, mz, this);
|
||||
if (extractedProtections != null)
|
||||
AppendToDictionary(protections, extractedProtections);
|
||||
#if NET20 || NET35
|
||||
}
|
||||
#else
|
||||
});
|
||||
#endif
|
||||
|
||||
return protections;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Handle extractable protections, such as executable packers
|
||||
/// </summary>
|
||||
/// <param name="classes">Set of classes returned from Exectuable scans</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>
|
||||
/// <returns>Set of protections found from extraction, null on error</returns>
|
||||
#if NET20 || NET35
|
||||
private Dictionary<string, Queue<string>>? HandleExtractableProtections<T>(Dictionary<T, string>.KeyCollection? classes, string fileName, LinearExecutable lex)
|
||||
#else
|
||||
private ConcurrentDictionary<string, ConcurrentQueue<string>>? HandleExtractableProtections(IEnumerable<object>? classes, string fileName, LinearExecutable lex)
|
||||
#endif
|
||||
{
|
||||
// If we have an invalid set of classes
|
||||
if (classes == null || !classes.Any())
|
||||
return null;
|
||||
|
||||
// Create the output dictionary
|
||||
#if NET20 || NET35
|
||||
var protections = new Dictionary<string, Queue<string>>();
|
||||
#else
|
||||
var protections = new ConcurrentDictionary<string, ConcurrentQueue<string>>();
|
||||
#endif
|
||||
|
||||
// If we have any extractable packers
|
||||
var extractables = classes.Where(c => c is IExtractableLinearExecutable).Select(c => c as IExtractableLinearExecutable);
|
||||
#if NET20 || NET35
|
||||
foreach (var extractable in extractables)
|
||||
#else
|
||||
Parallel.ForEach(extractables, extractable =>
|
||||
#endif
|
||||
{
|
||||
// If we have an invalid extractable somehow
|
||||
if (extractable == null)
|
||||
#if NET20 || NET35
|
||||
continue;
|
||||
#else
|
||||
return;
|
||||
#endif
|
||||
|
||||
// Get the protection for the class, if possible
|
||||
var extractedProtections = Handler.HandleExtractable(extractable, fileName, lex, this);
|
||||
if (extractedProtections != null)
|
||||
AppendToDictionary(protections, extractedProtections);
|
||||
#if NET20 || NET35
|
||||
}
|
||||
#else
|
||||
});
|
||||
#endif
|
||||
|
||||
return protections;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Handle extractable protections, such as executable packers
|
||||
/// </summary>
|
||||
/// <param name="classes">Set of classes returned from Exectuable scans</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>
|
||||
/// <returns>Set of protections found from extraction, null on error</returns>
|
||||
#if NET20 || NET35
|
||||
private Dictionary<string, Queue<string>>? HandleExtractableProtections<T>(Dictionary<T, string>.KeyCollection? classes, string fileName, NewExecutable nex)
|
||||
#else
|
||||
private ConcurrentDictionary<string, ConcurrentQueue<string>>? HandleExtractableProtections(IEnumerable<object>? classes, string fileName, NewExecutable nex)
|
||||
#endif
|
||||
{
|
||||
// If we have an invalid set of classes
|
||||
if (classes == null || !classes.Any())
|
||||
return null;
|
||||
|
||||
// Create the output dictionary
|
||||
#if NET20 || NET35
|
||||
var protections = new Dictionary<string, Queue<string>>();
|
||||
#else
|
||||
var protections = new ConcurrentDictionary<string, ConcurrentQueue<string>>();
|
||||
#endif
|
||||
|
||||
// If we have any extractable packers
|
||||
var extractables = classes.Where(c => c is IExtractableNewExecutable).Select(c => c as IExtractableNewExecutable);
|
||||
#if NET20 || NET35
|
||||
foreach (var extractable in extractables)
|
||||
#else
|
||||
Parallel.ForEach(extractables, extractable =>
|
||||
#endif
|
||||
{
|
||||
// If we have an invalid extractable somehow
|
||||
if (extractable == null)
|
||||
#if NET20 || NET35
|
||||
continue;
|
||||
#else
|
||||
return;
|
||||
#endif
|
||||
|
||||
// Get the protection for the class, if possible
|
||||
var extractedProtections = Handler.HandleExtractable(extractable, fileName, nex, this);
|
||||
if (extractedProtections != null)
|
||||
AppendToDictionary(protections, extractedProtections);
|
||||
#if NET20 || NET35
|
||||
}
|
||||
#else
|
||||
});
|
||||
#endif
|
||||
|
||||
return protections;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Handle extractable protections, such as executable packers
|
||||
/// </summary>
|
||||
/// <param name="classes">Set of classes returned from Exectuable scans</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>
|
||||
/// <returns>Set of protections found from extraction, null on error</returns>
|
||||
#if NET20 || NET35
|
||||
private Dictionary<string, Queue<string>>? HandleExtractableProtections<T>(Dictionary<T, string>.KeyCollection? classes, string fileName, PortableExecutable pex)
|
||||
#else
|
||||
private ConcurrentDictionary<string, ConcurrentQueue<string>>? HandleExtractableProtections(IEnumerable<object>? classes, string fileName, PortableExecutable pex)
|
||||
#endif
|
||||
{
|
||||
// If we have an invalid set of classes
|
||||
if (classes == null || !classes.Any())
|
||||
return null;
|
||||
|
||||
// Create the output dictionary
|
||||
#if NET20 || NET35
|
||||
var protections = new Dictionary<string, Queue<string>>();
|
||||
#else
|
||||
var protections = new ConcurrentDictionary<string, ConcurrentQueue<string>>();
|
||||
#endif
|
||||
|
||||
// If we have any extractable packers
|
||||
var extractables = classes.Where(c => c is IExtractablePortableExecutable).Select(c => c as IExtractablePortableExecutable);
|
||||
#if NET20 || NET35
|
||||
foreach (var extractable in extractables)
|
||||
#else
|
||||
Parallel.ForEach(extractables, extractable =>
|
||||
#endif
|
||||
{
|
||||
// If we have an invalid extractable somehow
|
||||
if (extractable == null)
|
||||
#if NET20 || NET35
|
||||
continue;
|
||||
#else
|
||||
return;
|
||||
#endif
|
||||
|
||||
// Get the protection for the class, if possible
|
||||
var extractedProtections = Handler.HandleExtractable(extractable, fileName, pex, this);
|
||||
if (extractedProtections != null)
|
||||
AppendToDictionary(protections, extractedProtections);
|
||||
#if NET20 || NET35
|
||||
|
||||
@@ -1,193 +0,0 @@
|
||||
namespace BinaryObjectScanner.Utilities
|
||||
{
|
||||
/// <summary>
|
||||
/// Subset of file types that are supported by the library
|
||||
/// </summary>
|
||||
public enum SupportedFileType
|
||||
{
|
||||
/// <summary>
|
||||
/// Unknown or unsupported
|
||||
/// </summary>
|
||||
UNKNOWN,
|
||||
|
||||
/// <summary>
|
||||
/// AACS media key block
|
||||
/// </summary>
|
||||
AACSMediaKeyBlock,
|
||||
|
||||
/// <summary>
|
||||
/// BD+ SVM
|
||||
/// </summary>
|
||||
BDPlusSVM,
|
||||
|
||||
/// <summary>
|
||||
/// BFPK custom archive
|
||||
/// </summary>
|
||||
BFPK,
|
||||
|
||||
/// <summary>
|
||||
/// Half-Life Level
|
||||
/// </summary>
|
||||
BSP,
|
||||
|
||||
/// <summary>
|
||||
/// bzip2 archive
|
||||
/// </summary>
|
||||
BZip2,
|
||||
|
||||
/// <summary>
|
||||
/// Compound File Binary
|
||||
/// </summary>
|
||||
CFB,
|
||||
|
||||
/// <summary>
|
||||
/// CTR Importable Archive
|
||||
/// </summary>
|
||||
CIA,
|
||||
|
||||
/// <summary>
|
||||
/// Executable or library
|
||||
/// </summary>
|
||||
Executable,
|
||||
|
||||
/// <summary>
|
||||
/// Half-Life Game Cache File
|
||||
/// </summary>
|
||||
GCF,
|
||||
|
||||
/// <summary>
|
||||
/// gzip archive
|
||||
/// </summary>
|
||||
GZIP,
|
||||
|
||||
/// <summary>
|
||||
/// Key-value pair INI file
|
||||
/// </summary>
|
||||
IniFile,
|
||||
|
||||
/// <summary>
|
||||
/// InstallShield archive v3
|
||||
/// </summary>
|
||||
InstallShieldArchiveV3,
|
||||
|
||||
/// <summary>
|
||||
/// InstallShield cabinet file
|
||||
/// </summary>
|
||||
InstallShieldCAB,
|
||||
|
||||
/// <summary>
|
||||
/// Link Data Security encrypted file
|
||||
/// </summary>
|
||||
LDSCRYPT,
|
||||
|
||||
/// <summary>
|
||||
/// Microsoft cabinet file
|
||||
/// </summary>
|
||||
MicrosoftCAB,
|
||||
|
||||
/// <summary>
|
||||
/// Microsoft LZ-compressed file
|
||||
/// </summary>
|
||||
MicrosoftLZ,
|
||||
|
||||
/// <summary>
|
||||
/// MPQ game data archive
|
||||
/// </summary>
|
||||
MPQ,
|
||||
|
||||
/// <summary>
|
||||
/// Nintendo 3DS cart image
|
||||
/// </summary>
|
||||
N3DS,
|
||||
|
||||
/// <summary>
|
||||
/// Half-Life No Cache File
|
||||
/// </summary>
|
||||
NCF,
|
||||
|
||||
/// <summary>
|
||||
/// Nintendo DS/DSi cart image
|
||||
/// </summary>
|
||||
Nitro,
|
||||
|
||||
/// <summary>
|
||||
/// Half-Life Package File
|
||||
/// </summary>
|
||||
PAK,
|
||||
|
||||
/// <summary>
|
||||
/// NovaLogic Game Archive Format
|
||||
/// </summary>
|
||||
PFF,
|
||||
|
||||
/// <summary>
|
||||
/// PKWARE ZIP archive and derivatives
|
||||
/// </summary>
|
||||
PKZIP,
|
||||
|
||||
/// <summary>
|
||||
/// PlayJ audio file
|
||||
/// </summary>
|
||||
PLJ,
|
||||
|
||||
/// <summary>
|
||||
/// Quantum archive
|
||||
/// </summary>
|
||||
Quantum,
|
||||
|
||||
/// <summary>
|
||||
/// RAR archive
|
||||
/// </summary>
|
||||
RAR,
|
||||
|
||||
/// <summary>
|
||||
/// 7-zip archive
|
||||
/// </summary>
|
||||
SevenZip,
|
||||
|
||||
/// <summary>
|
||||
/// StarForce FileSystem file
|
||||
/// </summary>
|
||||
SFFS,
|
||||
|
||||
/// <summary>
|
||||
/// SGA
|
||||
/// </summary>
|
||||
SGA,
|
||||
|
||||
/// <summary>
|
||||
/// Tape archive
|
||||
/// </summary>
|
||||
TapeArchive,
|
||||
|
||||
/// <summary>
|
||||
/// Various generic textfile formats
|
||||
/// </summary>
|
||||
Textfile,
|
||||
|
||||
/// <summary>
|
||||
/// Half-Life 2 Level
|
||||
/// </summary>
|
||||
VBSP,
|
||||
|
||||
/// <summary>
|
||||
/// Valve Package File
|
||||
/// </summary>
|
||||
VPK,
|
||||
|
||||
/// <summary>
|
||||
/// Half-Life Texture Package File
|
||||
/// </summary>
|
||||
WAD,
|
||||
|
||||
/// <summary>
|
||||
/// xz archive
|
||||
/// </summary>
|
||||
XZ,
|
||||
|
||||
/// <summary>
|
||||
/// Xbox Package File
|
||||
/// </summary>
|
||||
XZP,
|
||||
}
|
||||
}
|
||||
@@ -1,798 +0,0 @@
|
||||
using System;
|
||||
using SabreTools.Matching;
|
||||
|
||||
namespace BinaryObjectScanner.Utilities
|
||||
{
|
||||
public static class FileTypes
|
||||
{
|
||||
/// <summary>
|
||||
/// Get the supported file type for a magic string
|
||||
/// </summary>
|
||||
/// <remarks>Recommend sending in 16 bytes to check</remarks>
|
||||
public static SupportedFileType GetFileType(byte[] magic)
|
||||
{
|
||||
// If we have an invalid magic byte array
|
||||
if (magic == null || magic.Length == 0)
|
||||
return SupportedFileType.UNKNOWN;
|
||||
|
||||
// TODO: For all modelled types, use the constants instead of hardcoded values here
|
||||
#region AACSMediaKeyBlock
|
||||
|
||||
// Block starting with verify media key record
|
||||
if (magic.StartsWith(new byte?[] { 0x81, 0x00, 0x00, 0x14 }))
|
||||
return SupportedFileType.AACSMediaKeyBlock;
|
||||
|
||||
// Block starting with type and version record
|
||||
if (magic.StartsWith(new byte?[] { 0x10, 0x00, 0x00, 0x0C }))
|
||||
return SupportedFileType.AACSMediaKeyBlock;
|
||||
|
||||
#endregion
|
||||
|
||||
#region BDPlusSVM
|
||||
|
||||
if (magic.StartsWith(new byte?[] { 0x42, 0x44, 0x53, 0x56, 0x4D, 0x5F, 0x43, 0x43 }))
|
||||
return SupportedFileType.BDPlusSVM;
|
||||
|
||||
#endregion
|
||||
|
||||
#region BFPK
|
||||
|
||||
if (magic.StartsWith(new byte?[] { 0x42, 0x46, 0x50, 0x4b }))
|
||||
return SupportedFileType.BFPK;
|
||||
|
||||
#endregion
|
||||
|
||||
#region BSP
|
||||
|
||||
if (magic.StartsWith(new byte?[] { 0x1e, 0x00, 0x00, 0x00 }))
|
||||
return SupportedFileType.BSP;
|
||||
|
||||
#endregion
|
||||
|
||||
#region BZip2
|
||||
|
||||
if (magic.StartsWith(new byte?[] { 0x42, 0x52, 0x68 }))
|
||||
return SupportedFileType.BZip2;
|
||||
|
||||
#endregion
|
||||
|
||||
#region CFB
|
||||
|
||||
if (magic.StartsWith(new byte?[] { 0xD0, 0xCF, 0x11, 0xE0, 0xA1, 0xB1, 0x1A, 0xE1 }))
|
||||
return SupportedFileType.CFB;
|
||||
|
||||
#endregion
|
||||
|
||||
#region CIA
|
||||
|
||||
// No magic checks for CIA
|
||||
|
||||
#endregion
|
||||
|
||||
#region Executable
|
||||
|
||||
// DOS MZ executable file format (and descendants)
|
||||
if (magic.StartsWith(new byte?[] { 0x4d, 0x5a }))
|
||||
return SupportedFileType.Executable;
|
||||
|
||||
/*
|
||||
// None of the following are supported in scans yet
|
||||
|
||||
// Executable and Linkable Format
|
||||
if (magic.StartsWith(new byte?[] { 0x7f, 0x45, 0x4c, 0x46 }))
|
||||
return FileTypes.Executable;
|
||||
|
||||
// Mach-O binary (32-bit)
|
||||
if (magic.StartsWith(new byte?[] { 0xfe, 0xed, 0xfa, 0xce }))
|
||||
return FileTypes.Executable;
|
||||
|
||||
// Mach-O binary (32-bit, reverse byte ordering scheme)
|
||||
if (magic.StartsWith(new byte?[] { 0xce, 0xfa, 0xed, 0xfe }))
|
||||
return FileTypes.Executable;
|
||||
|
||||
// Mach-O binary (64-bit)
|
||||
if (magic.StartsWith(new byte?[] { 0xfe, 0xed, 0xfa, 0xcf }))
|
||||
return FileTypes.Executable;
|
||||
|
||||
// Mach-O binary (64-bit, reverse byte ordering scheme)
|
||||
if (magic.StartsWith(new byte?[] { 0xcf, 0xfa, 0xed, 0xfe }))
|
||||
return FileTypes.Executable;
|
||||
|
||||
// Prefrred Executable File Format
|
||||
if (magic.StartsWith(new byte?[] { 0x4a, 0x6f, 0x79, 0x21, 0x70, 0x65, 0x66, 0x66 }))
|
||||
return FileTypes.Executable;
|
||||
*/
|
||||
|
||||
#endregion
|
||||
|
||||
#region GCF
|
||||
|
||||
if (magic.StartsWith(new byte?[] { 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00 }))
|
||||
return SupportedFileType.GCF;
|
||||
|
||||
#endregion
|
||||
|
||||
#region GZIP
|
||||
|
||||
if (magic.StartsWith(new byte?[] { 0x1f, 0x8b }))
|
||||
return SupportedFileType.GZIP;
|
||||
|
||||
#endregion
|
||||
|
||||
#region IniFile
|
||||
|
||||
// No magic checks for IniFile
|
||||
|
||||
#endregion
|
||||
|
||||
#region InstallShieldArchiveV3
|
||||
|
||||
if (magic.StartsWith(new byte?[] { 0x13, 0x5D, 0x65, 0x8C }))
|
||||
return SupportedFileType.InstallShieldArchiveV3;
|
||||
|
||||
#endregion
|
||||
|
||||
#region InstallShieldCAB
|
||||
|
||||
if (magic.StartsWith(new byte?[] { 0x49, 0x53, 0x63 }))
|
||||
return SupportedFileType.InstallShieldCAB;
|
||||
|
||||
#endregion
|
||||
|
||||
#region LDSCRYPT
|
||||
|
||||
if (magic.StartsWith(new byte?[] { 0x4C, 0x44, 0x53, 0x43, 0x52, 0x59, 0x50, 0x54 }))
|
||||
return SupportedFileType.LDSCRYPT;
|
||||
|
||||
#endregion
|
||||
|
||||
#region MicrosoftCAB
|
||||
|
||||
if (magic.StartsWith(new byte?[] { 0x4d, 0x53, 0x43, 0x46 }))
|
||||
return SupportedFileType.MicrosoftCAB;
|
||||
|
||||
#endregion
|
||||
|
||||
#region MicrosoftLZ
|
||||
|
||||
if (magic.StartsWith(new byte?[] { 0x53, 0x5a, 0x44, 0x44, 0x88, 0xf0, 0x27, 0x33 }))
|
||||
return SupportedFileType.MicrosoftLZ;
|
||||
|
||||
#endregion
|
||||
|
||||
#region MPQ
|
||||
|
||||
if (magic.StartsWith(new byte?[] { 0x4d, 0x50, 0x51, 0x1a }))
|
||||
return SupportedFileType.MPQ;
|
||||
|
||||
if (magic.StartsWith(new byte?[] { 0x4d, 0x50, 0x51, 0x1b }))
|
||||
return SupportedFileType.MPQ;
|
||||
|
||||
#endregion
|
||||
|
||||
#region N3DS
|
||||
|
||||
// No magic checks for N3DS
|
||||
|
||||
#endregion
|
||||
|
||||
#region NCF
|
||||
|
||||
if (magic.StartsWith(new byte?[] { 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00 }))
|
||||
return SupportedFileType.NCF;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Nitro
|
||||
|
||||
// No magic checks for Nitro
|
||||
|
||||
#endregion
|
||||
|
||||
#region PAK
|
||||
|
||||
if (magic.StartsWith(new byte?[] { 0x50, 0x41, 0x43, 0x4B }))
|
||||
return SupportedFileType.PAK;
|
||||
|
||||
#endregion
|
||||
|
||||
#region PFF
|
||||
|
||||
// Version 2
|
||||
if (magic.StartsWith(new byte?[] { 0x14, 0x00, 0x00, 0x00, 0x50, 0x46, 0x46, 0x32 }))
|
||||
return SupportedFileType.PFF;
|
||||
|
||||
// Version 3
|
||||
if (magic.StartsWith(new byte?[] { 0x14, 0x00, 0x00, 0x00, 0x50, 0x46, 0x46, 0x33 }))
|
||||
return SupportedFileType.PFF;
|
||||
|
||||
// Version 4
|
||||
if (magic.StartsWith(new byte?[] { 0x14, 0x00, 0x00, 0x00, 0x50, 0x46, 0x46, 0x34 }))
|
||||
return SupportedFileType.PFF;
|
||||
|
||||
#endregion
|
||||
|
||||
#region PKZIP
|
||||
|
||||
// PKZIP (Unknown)
|
||||
if (magic.StartsWith(new byte?[] { 0x50, 0x4b, 0x00, 0x00 }))
|
||||
return SupportedFileType.PKZIP;
|
||||
|
||||
// PKZIP
|
||||
if (magic.StartsWith(new byte?[] { 0x50, 0x4b, 0x03, 0x04 }))
|
||||
return SupportedFileType.PKZIP;
|
||||
|
||||
// PKZIP (Empty Archive)
|
||||
if (magic.StartsWith(new byte?[] { 0x50, 0x4b, 0x05, 0x06 }))
|
||||
return SupportedFileType.PKZIP;
|
||||
|
||||
// PKZIP (Spanned Archive)
|
||||
if (magic.StartsWith(new byte?[] { 0x50, 0x4b, 0x07, 0x08 }))
|
||||
return SupportedFileType.PKZIP;
|
||||
|
||||
#endregion
|
||||
|
||||
#region PLJ
|
||||
|
||||
// https://www.iana.org/assignments/media-types/audio/vnd.everad.plj
|
||||
if (magic.StartsWith(new byte?[] { 0xFF, 0x9D, 0x53, 0x4B }))
|
||||
return SupportedFileType.PLJ;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Quantum
|
||||
|
||||
if (magic.StartsWith(new byte?[] { 0x44, 0x53 }))
|
||||
return SupportedFileType.Quantum;
|
||||
|
||||
#endregion
|
||||
|
||||
#region RAR
|
||||
|
||||
// RAR archive version 1.50 onwards
|
||||
if (magic.StartsWith(new byte?[] { 0x52, 0x61, 0x72, 0x21, 0x1a, 0x07, 0x00 }))
|
||||
return SupportedFileType.RAR;
|
||||
|
||||
// RAR archive version 5.0 onwards
|
||||
if (magic.StartsWith(new byte?[] { 0x52, 0x61, 0x72, 0x21, 0x1a, 0x07, 0x01, 0x00 }))
|
||||
return SupportedFileType.RAR;
|
||||
|
||||
#endregion
|
||||
|
||||
#region SevenZip
|
||||
|
||||
if (magic.StartsWith(new byte?[] { 0x37, 0x7a, 0xbc, 0xaf, 0x27, 0x1c }))
|
||||
return SupportedFileType.SevenZip;
|
||||
|
||||
#endregion
|
||||
|
||||
#region SFFS
|
||||
|
||||
// Found in Redump entry 81756, confirmed to be "StarForce Filesystem" by PiD.
|
||||
if (magic.StartsWith(new byte?[] { 0x53, 0x46, 0x46, 0x53 }))
|
||||
return SupportedFileType.SFFS;
|
||||
|
||||
#endregion
|
||||
|
||||
#region SGA
|
||||
|
||||
if (magic.StartsWith(new byte?[] { 0x5F, 0x41, 0x52, 0x43, 0x48, 0x49, 0x56, 0x45 }))
|
||||
return SupportedFileType.SGA;
|
||||
|
||||
#endregion
|
||||
|
||||
#region TapeArchive
|
||||
|
||||
if (magic.StartsWith(new byte?[] { 0x75, 0x73, 0x74, 0x61, 0x72, 0x00, 0x30, 0x30 }))
|
||||
return SupportedFileType.TapeArchive;
|
||||
|
||||
if (magic.StartsWith(new byte?[] { 0x75, 0x73, 0x74, 0x61, 0x72, 0x20, 0x20, 0x00 }))
|
||||
return SupportedFileType.TapeArchive;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Textfile
|
||||
|
||||
// Not all textfiles can be determined through magic number
|
||||
|
||||
// HTML
|
||||
if (magic.StartsWith(new byte?[] { 0x3c, 0x68, 0x74, 0x6d, 0x6c }))
|
||||
return SupportedFileType.Textfile;
|
||||
|
||||
// HTML and XML
|
||||
if (magic.StartsWith(new byte?[] { 0x3c, 0x21, 0x44, 0x4f, 0x43, 0x54, 0x59, 0x50, 0x45 }))
|
||||
return SupportedFileType.Textfile;
|
||||
|
||||
// InstallShield Compiled Rules
|
||||
if (magic.StartsWith(new byte?[] { 0x61, 0x4C, 0x75, 0x5A }))
|
||||
return SupportedFileType.Textfile;
|
||||
|
||||
// Microsoft Office File (old)
|
||||
if (magic.StartsWith(new byte?[] { 0xd0, 0xcf, 0x11, 0xe0, 0xa1, 0xb1, 0x1a, 0xe1 }))
|
||||
return SupportedFileType.Textfile;
|
||||
|
||||
// Rich Text File
|
||||
if (magic.StartsWith(new byte?[] { 0x7b, 0x5c, 0x72, 0x74, 0x66, 0x31 }))
|
||||
return SupportedFileType.Textfile;
|
||||
|
||||
// Windows Help File
|
||||
if (magic.StartsWith(new byte?[] { 0x3F, 0x5F, 0x03, 0x00 }))
|
||||
return SupportedFileType.Textfile;
|
||||
|
||||
// XML
|
||||
// "<?xml"
|
||||
if (magic.StartsWith(new byte?[] { 0x3C, 0x3F, 0x78, 0x6D, 0x6C }))
|
||||
return SupportedFileType.Textfile;
|
||||
|
||||
#endregion
|
||||
|
||||
#region VBSP
|
||||
|
||||
if (magic.StartsWith(new byte?[] { 0x56, 0x42, 0x53, 0x50 }))
|
||||
return SupportedFileType.VBSP;
|
||||
|
||||
#endregion
|
||||
|
||||
#region VPK
|
||||
|
||||
if (magic.StartsWith(new byte?[] { 0x34, 0x12, 0xaa, 0x55 }))
|
||||
return SupportedFileType.VPK;
|
||||
|
||||
#endregion
|
||||
|
||||
#region WAD
|
||||
|
||||
if (magic.StartsWith(new byte?[] { 0x57, 0x41, 0x44, 0x33 }))
|
||||
return SupportedFileType.WAD;
|
||||
|
||||
#endregion
|
||||
|
||||
#region XZ
|
||||
|
||||
if (magic.StartsWith(new byte?[] { 0xfd, 0x37, 0x7a, 0x58, 0x5a, 0x00 }))
|
||||
return SupportedFileType.XZ;
|
||||
|
||||
#endregion
|
||||
|
||||
#region XZP
|
||||
|
||||
if (magic.StartsWith(new byte?[] { 0x70, 0x69, 0x5A, 0x78 }))
|
||||
return SupportedFileType.XZP;
|
||||
|
||||
#endregion
|
||||
|
||||
// We couldn't find a supported match
|
||||
return SupportedFileType.UNKNOWN;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the supported file type for an extension
|
||||
/// </summary>
|
||||
/// <remarks>This is less accurate than a magic string match</remarks>
|
||||
public static SupportedFileType GetFileType(string extension)
|
||||
{
|
||||
// If we have an invalid extension
|
||||
if (string.IsNullOrEmpty(extension))
|
||||
return SupportedFileType.UNKNOWN;
|
||||
|
||||
// Normalize the extension
|
||||
extension = extension.TrimStart('.').Trim();
|
||||
|
||||
#region AACSMediaKeyBlock
|
||||
|
||||
// Shares an extension with INF setup information so it can't be used accurately
|
||||
// Blu-ray
|
||||
// if (extension.Equals("inf", StringComparison.OrdinalIgnoreCase))
|
||||
// return SupportedFileType.AACSMediaKeyBlock;
|
||||
|
||||
// HD-DVD
|
||||
if (extension.Equals("aacs", StringComparison.OrdinalIgnoreCase))
|
||||
return SupportedFileType.AACSMediaKeyBlock;
|
||||
|
||||
#endregion
|
||||
|
||||
#region BDPlusSVM
|
||||
|
||||
if (extension.Equals("svm", StringComparison.OrdinalIgnoreCase))
|
||||
return SupportedFileType.BDPlusSVM;
|
||||
|
||||
#endregion
|
||||
|
||||
#region BFPK
|
||||
|
||||
// No extensions registered for BFPK
|
||||
|
||||
#endregion
|
||||
|
||||
#region BSP
|
||||
|
||||
// Shares an extension with VBSP so it can't be used accurately
|
||||
// if (extension.Equals("bsp", StringComparison.OrdinalIgnoreCase))
|
||||
// return SupportedFileType.BSP;
|
||||
|
||||
#endregion
|
||||
|
||||
#region BZip2
|
||||
|
||||
if (extension.Equals("bz2", StringComparison.OrdinalIgnoreCase))
|
||||
return SupportedFileType.BZip2;
|
||||
|
||||
#endregion
|
||||
|
||||
#region CFB
|
||||
|
||||
// Installer package
|
||||
if (extension.Equals("msi", StringComparison.OrdinalIgnoreCase))
|
||||
return SupportedFileType.CFB;
|
||||
|
||||
// Merge module
|
||||
else if (extension.Equals("msm", StringComparison.OrdinalIgnoreCase))
|
||||
return SupportedFileType.CFB;
|
||||
|
||||
// Patch Package
|
||||
else if (extension.Equals("msp", StringComparison.OrdinalIgnoreCase))
|
||||
return SupportedFileType.CFB;
|
||||
|
||||
// Transform
|
||||
else if (extension.Equals("mst", StringComparison.OrdinalIgnoreCase))
|
||||
return SupportedFileType.CFB;
|
||||
|
||||
// Patch Creation Properties
|
||||
else if (extension.Equals("pcp", StringComparison.OrdinalIgnoreCase))
|
||||
return SupportedFileType.CFB;
|
||||
|
||||
#endregion
|
||||
|
||||
#region CIA
|
||||
|
||||
if (extension.Equals("cia", StringComparison.OrdinalIgnoreCase))
|
||||
return SupportedFileType.CIA;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Executable
|
||||
|
||||
// DOS MZ executable file format (and descendants)
|
||||
if (extension.Equals("exe", StringComparison.OrdinalIgnoreCase))
|
||||
return SupportedFileType.Executable;
|
||||
|
||||
// DOS MZ library file format (and descendants)
|
||||
if (extension.Equals("dll", StringComparison.OrdinalIgnoreCase))
|
||||
return SupportedFileType.Executable;
|
||||
|
||||
#endregion
|
||||
|
||||
#region GCF
|
||||
|
||||
if (extension.Equals("gcf", StringComparison.OrdinalIgnoreCase))
|
||||
return SupportedFileType.GCF;
|
||||
|
||||
#endregion
|
||||
|
||||
#region GZIP
|
||||
|
||||
if (extension.Equals("gz", StringComparison.OrdinalIgnoreCase))
|
||||
return SupportedFileType.GZIP;
|
||||
|
||||
#endregion
|
||||
|
||||
#region IniFile
|
||||
|
||||
if (extension.Equals("ini", StringComparison.OrdinalIgnoreCase))
|
||||
return SupportedFileType.IniFile;
|
||||
|
||||
#endregion
|
||||
|
||||
#region InstallShieldArchiveV3
|
||||
|
||||
if (extension.Equals("z", StringComparison.OrdinalIgnoreCase))
|
||||
return SupportedFileType.InstallShieldArchiveV3;
|
||||
|
||||
#endregion
|
||||
|
||||
#region InstallShieldCAB
|
||||
|
||||
// No extensions registered for InstallShieldCAB
|
||||
// Both InstallShieldCAB and MicrosoftCAB share the same extension
|
||||
|
||||
#endregion
|
||||
|
||||
#region MicrosoftCAB
|
||||
|
||||
// No extensions registered for InstallShieldCAB
|
||||
// Both InstallShieldCAB and MicrosoftCAB share the same extension
|
||||
|
||||
#endregion
|
||||
|
||||
#region MPQ
|
||||
|
||||
if (extension.Equals("mpq", StringComparison.OrdinalIgnoreCase))
|
||||
return SupportedFileType.MPQ;
|
||||
|
||||
#endregion
|
||||
|
||||
#region N3DS
|
||||
|
||||
// 3DS cart image
|
||||
if (extension.Equals("3ds", StringComparison.OrdinalIgnoreCase))
|
||||
return SupportedFileType.N3DS;
|
||||
|
||||
// CIA package -- Not currently supported
|
||||
// else if (extension.Equals("cia", StringComparison.OrdinalIgnoreCase))
|
||||
// return SupportedFileType.N3DS;
|
||||
|
||||
#endregion
|
||||
|
||||
#region NCF
|
||||
|
||||
if (extension.Equals("ncf", StringComparison.OrdinalIgnoreCase))
|
||||
return SupportedFileType.NCF;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Nitro
|
||||
|
||||
// DS cart image
|
||||
if (extension.Equals("nds", StringComparison.OrdinalIgnoreCase))
|
||||
return SupportedFileType.Nitro;
|
||||
|
||||
// DS development cart image
|
||||
else if (extension.Equals("srl", StringComparison.OrdinalIgnoreCase))
|
||||
return SupportedFileType.Nitro;
|
||||
|
||||
// DSi cart image
|
||||
else if (extension.Equals("dsi", StringComparison.OrdinalIgnoreCase))
|
||||
return SupportedFileType.Nitro;
|
||||
|
||||
// iQue DS cart image
|
||||
else if (extension.Equals("ids", StringComparison.OrdinalIgnoreCase))
|
||||
return SupportedFileType.Nitro;
|
||||
|
||||
#endregion
|
||||
|
||||
#region PAK
|
||||
|
||||
// No extensions registered for PAK
|
||||
// Both PAK and Quantum share one extension
|
||||
// if (extension.Equals("pak", StringComparison.OrdinalIgnoreCase))
|
||||
// return SupportedFileType.PAK;
|
||||
|
||||
#endregion
|
||||
|
||||
#region PFF
|
||||
|
||||
if (extension.Equals("pff", StringComparison.OrdinalIgnoreCase))
|
||||
return SupportedFileType.PFF;
|
||||
|
||||
#endregion
|
||||
|
||||
#region PKZIP
|
||||
|
||||
// PKZIP
|
||||
if (extension.Equals("zip", StringComparison.OrdinalIgnoreCase))
|
||||
return SupportedFileType.PKZIP;
|
||||
|
||||
// Android package
|
||||
if (extension.Equals("apk", StringComparison.OrdinalIgnoreCase))
|
||||
return SupportedFileType.PKZIP;
|
||||
|
||||
// Java archive
|
||||
if (extension.Equals("jar", StringComparison.OrdinalIgnoreCase))
|
||||
return SupportedFileType.PKZIP;
|
||||
|
||||
// Google Earth saved working session file
|
||||
if (extension.Equals("kmz", StringComparison.OrdinalIgnoreCase))
|
||||
return SupportedFileType.PKZIP;
|
||||
|
||||
// KWord document
|
||||
if (extension.Equals("kwd", StringComparison.OrdinalIgnoreCase))
|
||||
return SupportedFileType.PKZIP;
|
||||
|
||||
// Microsoft Office Open XML Format (OOXML) Document
|
||||
if (extension.Equals("docx", StringComparison.OrdinalIgnoreCase))
|
||||
return SupportedFileType.PKZIP;
|
||||
|
||||
// Microsoft Office Open XML Format (OOXML) Presentation
|
||||
if (extension.Equals("pptx", StringComparison.OrdinalIgnoreCase))
|
||||
return SupportedFileType.PKZIP;
|
||||
|
||||
// Microsoft Office Open XML Format (OOXML) Spreadsheet
|
||||
if (extension.Equals("xlsx", StringComparison.OrdinalIgnoreCase))
|
||||
return SupportedFileType.PKZIP;
|
||||
|
||||
// OpenDocument text document
|
||||
if (extension.Equals("odt", StringComparison.OrdinalIgnoreCase))
|
||||
return SupportedFileType.PKZIP;
|
||||
|
||||
// OpenDocument presentation
|
||||
if (extension.Equals("odp", StringComparison.OrdinalIgnoreCase))
|
||||
return SupportedFileType.PKZIP;
|
||||
|
||||
// OpenDocument text document template
|
||||
if (extension.Equals("ott", StringComparison.OrdinalIgnoreCase))
|
||||
return SupportedFileType.PKZIP;
|
||||
|
||||
// Microsoft Open XML paper specification file
|
||||
if (extension.Equals("oxps", StringComparison.OrdinalIgnoreCase))
|
||||
return SupportedFileType.PKZIP;
|
||||
|
||||
// OpenOffice spreadsheet
|
||||
if (extension.Equals("sxc", StringComparison.OrdinalIgnoreCase))
|
||||
return SupportedFileType.PKZIP;
|
||||
|
||||
// OpenOffice drawing
|
||||
if (extension.Equals("sxd", StringComparison.OrdinalIgnoreCase))
|
||||
return SupportedFileType.PKZIP;
|
||||
|
||||
// OpenOffice presentation
|
||||
if (extension.Equals("sxi", StringComparison.OrdinalIgnoreCase))
|
||||
return SupportedFileType.PKZIP;
|
||||
|
||||
// OpenOffice word processing
|
||||
if (extension.Equals("sxw", StringComparison.OrdinalIgnoreCase))
|
||||
return SupportedFileType.PKZIP;
|
||||
|
||||
// StarOffice spreadsheet
|
||||
if (extension.Equals("sxc", StringComparison.OrdinalIgnoreCase))
|
||||
return SupportedFileType.PKZIP;
|
||||
|
||||
// Windows Media compressed skin file
|
||||
if (extension.Equals("wmz", StringComparison.OrdinalIgnoreCase))
|
||||
return SupportedFileType.PKZIP;
|
||||
|
||||
// Mozilla Browser Archive
|
||||
if (extension.Equals("xpi", StringComparison.OrdinalIgnoreCase))
|
||||
return SupportedFileType.PKZIP;
|
||||
|
||||
// XML paper specification file
|
||||
if (extension.Equals("xps", StringComparison.OrdinalIgnoreCase))
|
||||
return SupportedFileType.PKZIP;
|
||||
|
||||
// eXact Packager Models
|
||||
if (extension.Equals("xpt", StringComparison.OrdinalIgnoreCase))
|
||||
return SupportedFileType.PKZIP;
|
||||
|
||||
#endregion
|
||||
|
||||
#region PLJ
|
||||
|
||||
// https://www.iana.org/assignments/media-types/audio/vnd.everad.plj
|
||||
if (extension.Equals("plj", StringComparison.OrdinalIgnoreCase))
|
||||
return SupportedFileType.PLJ;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Quantum
|
||||
|
||||
if (extension.Equals("q", StringComparison.OrdinalIgnoreCase))
|
||||
return SupportedFileType.Quantum;
|
||||
|
||||
// Both PAK and Quantum share one extension
|
||||
// if (extension.Equals("pak", StringComparison.OrdinalIgnoreCase))
|
||||
// return SupportedFileType.Quantum;
|
||||
|
||||
#endregion
|
||||
|
||||
#region RAR
|
||||
|
||||
if (extension.Equals("rar", StringComparison.OrdinalIgnoreCase))
|
||||
return SupportedFileType.RAR;
|
||||
|
||||
#endregion
|
||||
|
||||
#region SevenZip
|
||||
|
||||
if (extension.Equals("7z", StringComparison.OrdinalIgnoreCase))
|
||||
return SupportedFileType.SevenZip;
|
||||
|
||||
#endregion
|
||||
|
||||
#region SGA
|
||||
|
||||
if (extension.Equals("sga", StringComparison.OrdinalIgnoreCase))
|
||||
return SupportedFileType.SGA;
|
||||
|
||||
#endregion
|
||||
|
||||
#region TapeArchive
|
||||
|
||||
if (extension.Equals("tar", StringComparison.OrdinalIgnoreCase))
|
||||
return SupportedFileType.SevenZip;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Textfile
|
||||
|
||||
// "Description in Zip"
|
||||
if (extension.Equals("diz", StringComparison.OrdinalIgnoreCase))
|
||||
return SupportedFileType.Textfile;
|
||||
|
||||
// Generic textfile (no header)
|
||||
if (extension.Equals("txt", StringComparison.OrdinalIgnoreCase))
|
||||
return SupportedFileType.Textfile;
|
||||
|
||||
// HTML
|
||||
if (extension.Equals("htm", StringComparison.OrdinalIgnoreCase))
|
||||
return SupportedFileType.Textfile;
|
||||
if (extension.Equals("html", StringComparison.OrdinalIgnoreCase))
|
||||
return SupportedFileType.Textfile;
|
||||
|
||||
// InstallShield Script
|
||||
if (extension.Equals("ins", StringComparison.OrdinalIgnoreCase))
|
||||
return SupportedFileType.Textfile;
|
||||
|
||||
// Microsoft Office File (old)
|
||||
if (extension.Equals("doc", StringComparison.OrdinalIgnoreCase))
|
||||
return SupportedFileType.Textfile;
|
||||
|
||||
// Property list
|
||||
if (extension.Equals("plist", StringComparison.OrdinalIgnoreCase))
|
||||
return SupportedFileType.Textfile;
|
||||
|
||||
// Rich Text File
|
||||
if (extension.Equals("rtf", StringComparison.OrdinalIgnoreCase))
|
||||
return SupportedFileType.Textfile;
|
||||
|
||||
// Setup information
|
||||
if (extension.Equals("inf", StringComparison.OrdinalIgnoreCase))
|
||||
return SupportedFileType.Textfile;
|
||||
|
||||
// Windows Help File
|
||||
if (extension.Equals("hlp", StringComparison.OrdinalIgnoreCase))
|
||||
return SupportedFileType.Textfile;
|
||||
|
||||
// WZC
|
||||
if (extension.Equals("wzc", StringComparison.OrdinalIgnoreCase))
|
||||
return SupportedFileType.Textfile;
|
||||
|
||||
// XML
|
||||
if (extension.Equals("xml", StringComparison.OrdinalIgnoreCase))
|
||||
return SupportedFileType.Textfile;
|
||||
|
||||
|
||||
|
||||
#endregion
|
||||
|
||||
#region VBSP
|
||||
|
||||
// Shares an extension with BSP so it can't be used accurately
|
||||
// if (extension.Equals("bsp", StringComparison.OrdinalIgnoreCase))
|
||||
// return SupportedFileType.VBSP;
|
||||
|
||||
#endregion
|
||||
|
||||
#region VPK
|
||||
|
||||
// Common extension so this cannot be used accurately
|
||||
// if (extension.Equals("vpk", StringComparison.OrdinalIgnoreCase))
|
||||
// return SupportedFileType.VPK;
|
||||
|
||||
#endregion
|
||||
|
||||
#region WAD
|
||||
|
||||
// Common extension so this cannot be used accurately
|
||||
// if (extension.Equals("wad", StringComparison.OrdinalIgnoreCase))
|
||||
// return SupportedFileType.WAD;
|
||||
|
||||
#endregion
|
||||
|
||||
#region XZ
|
||||
|
||||
if (extension.Equals("xz", StringComparison.OrdinalIgnoreCase))
|
||||
return SupportedFileType.XZ;
|
||||
|
||||
#endregion
|
||||
|
||||
#region XZP
|
||||
|
||||
if (extension.Equals("xzp", StringComparison.OrdinalIgnoreCase))
|
||||
return SupportedFileType.XZP;
|
||||
|
||||
#endregion
|
||||
|
||||
// We couldn't find a supported match
|
||||
return SupportedFileType.UNKNOWN;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,114 +0,0 @@
|
||||
using System.IO;
|
||||
using SabreTools.IO;
|
||||
using SabreTools.Matching;
|
||||
using SabreTools.Serialization.Interfaces;
|
||||
using SabreTools.Serialization.Wrappers;
|
||||
|
||||
namespace BinaryObjectScanner.Utilities
|
||||
{
|
||||
public static class WrapperFactory
|
||||
{
|
||||
/// <summary>
|
||||
/// Create an instance of a wrapper based on file type
|
||||
/// </summary>
|
||||
public static IWrapper? CreateWrapper(SupportedFileType fileType, Stream? data)
|
||||
{
|
||||
switch (fileType)
|
||||
{
|
||||
case SupportedFileType.AACSMediaKeyBlock: return AACSMediaKeyBlock.Create(data);
|
||||
case SupportedFileType.BDPlusSVM: return BDPlusSVM.Create(data);
|
||||
case SupportedFileType.BFPK: return BFPK.Create(data);
|
||||
case SupportedFileType.BSP: return BSP.Create(data);
|
||||
//case SupportedFileType.BZip2: return BZip2.Create(data);
|
||||
case SupportedFileType.CFB: return CFB.Create(data);
|
||||
case SupportedFileType.CIA: return CIA.Create(data);
|
||||
case SupportedFileType.Executable: return CreateExecutableWrapper(data);
|
||||
case SupportedFileType.GCF: return GCF.Create(data);
|
||||
//case SupportedFileType.GZIP: return GZIP.Create(data);
|
||||
//case SupportedFileType.IniFile: return IniFile.Create(data);
|
||||
//case SupportedFileType.InstallShieldArchiveV3: return InstallShieldArchiveV3.Create(data);
|
||||
case SupportedFileType.InstallShieldCAB: return InstallShieldCabinet.Create(data);
|
||||
//case SupportedFileType.LDSCRYPT: return LDSCRYPT.Create(data);
|
||||
case SupportedFileType.MicrosoftCAB: return MicrosoftCabinet.Create(data);
|
||||
//case SupportedFileType.MicrosoftLZ: return MicrosoftLZ.Create(data);
|
||||
//case SupportedFileType.MPQ: return MoPaQ.Create(data);
|
||||
case SupportedFileType.N3DS: return N3DS.Create(data);
|
||||
case SupportedFileType.NCF: return NCF.Create(data);
|
||||
case SupportedFileType.Nitro: return Nitro.Create(data);
|
||||
case SupportedFileType.PAK: return PAK.Create(data);
|
||||
case SupportedFileType.PFF: return PFF.Create(data);
|
||||
//case SupportedFileType.PKZIP: return PKZIP.Create(data);
|
||||
case SupportedFileType.PLJ: return PlayJAudioFile.Create(data);
|
||||
case SupportedFileType.Quantum: return Quantum.Create(data);
|
||||
//case SupportedFileType.RAR: return RAR.Create(data);
|
||||
//case SupportedFileType.SevenZip: return SevenZip.Create(data);
|
||||
//case SupportedFileType.SFFS: return SFFS.Create(data);
|
||||
case SupportedFileType.SGA: return SGA.Create(data);
|
||||
//case SupportedFileType.TapeArchive: return TapeArchive.Create(data);
|
||||
//case SupportedFileType.Textfile: return Textfile.Create(data);
|
||||
case SupportedFileType.VBSP: return VBSP.Create(data);
|
||||
case SupportedFileType.VPK: return VPK.Create(data);
|
||||
case SupportedFileType.WAD: return WAD.Create(data);
|
||||
//case SupportedFileType.XZ: return XZ.Create(data);
|
||||
case SupportedFileType.XZP: return XZP.Create(data);
|
||||
default: return null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create an instance of a wrapper based on the executable type
|
||||
/// </summary>
|
||||
/// <param name="stream">Stream data to parse</param>
|
||||
/// <returns>IWrapper representing the executable, null on error</returns>
|
||||
public static IWrapper? CreateExecutableWrapper(Stream? stream)
|
||||
{
|
||||
// If we have no stream
|
||||
if (stream == null)
|
||||
return null;
|
||||
|
||||
// Try to get an MS-DOS wrapper first
|
||||
IWrapper? wrapper = MSDOS.Create(stream);
|
||||
if (wrapper == null || !(wrapper is MSDOS msdos))
|
||||
return null;
|
||||
|
||||
// Check for a valid new executable address
|
||||
if (msdos.Model.Header?.NewExeHeaderAddr == null || msdos.Model.Header.NewExeHeaderAddr >= stream.Length)
|
||||
return wrapper;
|
||||
|
||||
// Try to read the executable info
|
||||
stream.Seek(msdos.Model.Header.NewExeHeaderAddr, SeekOrigin.Begin);
|
||||
var magic = stream.ReadBytes(4);
|
||||
|
||||
// If we didn't get valid data at the offset
|
||||
if (magic == null)
|
||||
{
|
||||
return wrapper;
|
||||
}
|
||||
|
||||
// New Executable
|
||||
else if (magic.StartsWith(SabreTools.Models.NewExecutable.Constants.SignatureBytes))
|
||||
{
|
||||
stream.Seek(0, SeekOrigin.Begin);
|
||||
return NewExecutable.Create(stream);
|
||||
}
|
||||
|
||||
// Linear Executable
|
||||
else if (magic.StartsWith(SabreTools.Models.LinearExecutable.Constants.LESignatureBytes)
|
||||
|| magic.StartsWith(SabreTools.Models.LinearExecutable.Constants.LXSignatureBytes))
|
||||
{
|
||||
stream.Seek(0, SeekOrigin.Begin);
|
||||
return LinearExecutable.Create(stream);
|
||||
}
|
||||
|
||||
// Portable Executable
|
||||
else if (magic.StartsWith(SabreTools.Models.PortableExecutable.Constants.SignatureBytes))
|
||||
{
|
||||
stream.Seek(0, SeekOrigin.Begin);
|
||||
return PortableExecutable.Create(stream);
|
||||
}
|
||||
|
||||
// Everything else fails
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
# BinaryObjectScanner
|
||||
# Binary Object Scanner
|
||||
|
||||
[](https://ci.appveyor.com/project/mnadareski/BinaryObjectScanner)
|
||||
[](https://github.com/SabreTools/BinaryObjectScanner/actions/workflows/build_test.yml)
|
||||
@@ -6,13 +6,12 @@
|
||||
|
||||
C# protection, packer, and archive scanning library. This currently compiles as a library so it can be used in any C# application. A reference application called `Test` is also included to demonstrate the abilities of the library. For an example of a program implementing the library, see [MPF](https://github.com/SabreTools/MPF).
|
||||
|
||||
The following libraries (or ports thereof) are used for file handling:
|
||||
The following non-project libraries (or ports thereof) are used for file handling:
|
||||
|
||||
- [LessIO](https://github.com/activescott/LessIO) - Used by libmspack4n for IO handling
|
||||
- [libmspack4n](https://github.com/activescott/libmspack4n) MS-CAB extraction [Unused in .NET Frawework 2.0/3.5/4.0 and non-Windows builds due to Windows-specific libraries]
|
||||
- [openmcdf](https://github.com/ironfede/openmcdf) - MSI extraction
|
||||
- [SharpCompress](https://github.com/adamhathcock/sharpcompress) - Common archive format extraction
|
||||
- [SharpZipLib](https://github.com/icsharpcode/SharpZipLib) - zlib-based extraction
|
||||
- [StormLibSharp](https://github.com/robpaveza/stormlibsharp) - MoPaQ extraction [Unused in .NET Frawework 2.0/3.5/4.0 and non-Windows builds due to Windows-specific libraries]
|
||||
- [UnshieldSharp](https://github.com/mnadareski/UnshieldSharp) - InstallShield CAB extraction
|
||||
- [WiseUnpacker](https://github.com/mnadareski/WiseUnpacker) - Wise Installer extraction
|
||||
@@ -93,8 +92,10 @@ Below is a list of protections detected by BinaryObjectScanner. The two columns
|
||||
| Protect DVD-Video | False | True | Unconfirmed¹ |
|
||||
| PlayStation Anti-modchip | True | False | En/Jp, not "Red Hand"; PSX executables only |
|
||||
| Rainbow Sentinel | True | True | |
|
||||
| RealArcade | True | True | |
|
||||
| Ring PROTECH / ProRing | True | True | Partially unconfirmed² |
|
||||
| RipGuard | True | True | Partially unconfirmed² |
|
||||
| Roxxe | True | False | |
|
||||
| SafeDisc / SafeCast | True | True | Can't distinguish between some versions of SafeDisc and SafeCast |
|
||||
| SafeLock | False | True | |
|
||||
| SecuROM | True | True | v8.x and White Label detected partially² |
|
||||
|
||||
@@ -1,12 +1,13 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
#if NET452_OR_GREATER || NETCOREAPP
|
||||
using System.Text;
|
||||
#endif
|
||||
using BinaryObjectScanner.Utilities;
|
||||
#if NET40_OR_GREATER || NETCOREAPP
|
||||
using OpenMcdf;
|
||||
#endif
|
||||
using SabreTools.IO;
|
||||
using SabreTools.IO.Extensions;
|
||||
using SabreTools.Serialization.Wrappers;
|
||||
#if NET462_OR_GREATER || NETCOREAPP
|
||||
using SharpCompress.Archives;
|
||||
@@ -19,10 +20,7 @@ using SharpCompress.Compressors;
|
||||
using SharpCompress.Compressors.BZip2;
|
||||
using SharpCompress.Compressors.Xz;
|
||||
#endif
|
||||
#if NET40_OR_GREATER || NETCOREAPP
|
||||
using UnshieldSharp.Archive;
|
||||
using UnshieldSharp.Cabinet;
|
||||
#endif
|
||||
|
||||
namespace Test
|
||||
{
|
||||
@@ -44,11 +42,7 @@ namespace Test
|
||||
}
|
||||
else if (Directory.Exists(path))
|
||||
{
|
||||
#if NET20 || NET35
|
||||
foreach (string file in Directory.GetFiles(path, "*", SearchOption.AllDirectories))
|
||||
#else
|
||||
foreach (string file in Directory.EnumerateFiles(path, "*", SearchOption.AllDirectories))
|
||||
#endif
|
||||
foreach (string file in IOExtensions.SafeEnumerateFiles(path, "*", SearchOption.AllDirectories))
|
||||
{
|
||||
ExtractFile(file, outputDirectory);
|
||||
}
|
||||
@@ -72,13 +66,13 @@ namespace Test
|
||||
stream.Seek(0, SeekOrigin.Begin);
|
||||
|
||||
// Get the file type
|
||||
SupportedFileType ft = FileTypes.GetFileType(magic ?? []);
|
||||
WrapperType ft = WrapperFactory.GetFileType(magic ?? []);
|
||||
|
||||
// Executables technically can be "extracted", but let's ignore that
|
||||
// TODO: Support executables that include other stuff
|
||||
|
||||
// 7-zip
|
||||
if (ft == SupportedFileType.SevenZip)
|
||||
if (ft == WrapperType.SevenZip)
|
||||
{
|
||||
// Build the archive information
|
||||
Console.WriteLine("Extracting 7-zip contents");
|
||||
@@ -97,10 +91,14 @@ namespace Test
|
||||
// If an individual entry fails
|
||||
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(outputDirectory, entry.Key);
|
||||
entry.WriteToFile(tempFile);
|
||||
}
|
||||
@@ -120,7 +118,7 @@ namespace Test
|
||||
}
|
||||
|
||||
// BFPK archive
|
||||
else if (ft == SupportedFileType.BFPK)
|
||||
else if (ft == WrapperType.BFPK)
|
||||
{
|
||||
// Build the BFPK information
|
||||
Console.WriteLine("Extracting BFPK contents");
|
||||
@@ -147,7 +145,7 @@ namespace Test
|
||||
}
|
||||
|
||||
// BSP
|
||||
else if (ft == SupportedFileType.BSP)
|
||||
else if (ft == WrapperType.BSP)
|
||||
{
|
||||
// Build the BSP information
|
||||
Console.WriteLine("Extracting BSP contents");
|
||||
@@ -175,7 +173,7 @@ namespace Test
|
||||
}
|
||||
|
||||
// bzip2
|
||||
else if (ft == SupportedFileType.BZip2)
|
||||
else if (ft == WrapperType.BZip2)
|
||||
{
|
||||
// Build the bzip2 information
|
||||
Console.WriteLine("Extracting bzip2 contents");
|
||||
@@ -203,7 +201,7 @@ namespace Test
|
||||
}
|
||||
|
||||
// CFB
|
||||
else if (ft == SupportedFileType.CFB)
|
||||
else if (ft == WrapperType.CFB)
|
||||
{
|
||||
// Build the installer information
|
||||
Console.WriteLine("Extracting CFB contents");
|
||||
@@ -253,7 +251,7 @@ namespace Test
|
||||
}
|
||||
|
||||
// GCF
|
||||
else if (ft == SupportedFileType.GCF)
|
||||
else if (ft == WrapperType.GCF)
|
||||
{
|
||||
// Build the GCF information
|
||||
Console.WriteLine("Extracting GCF contents");
|
||||
@@ -280,7 +278,7 @@ namespace Test
|
||||
}
|
||||
|
||||
// gzip
|
||||
else if (ft == SupportedFileType.GZIP)
|
||||
else if (ft == WrapperType.GZIP)
|
||||
{
|
||||
// Build the gzip information
|
||||
Console.WriteLine("Extracting gzip contents");
|
||||
@@ -296,10 +294,14 @@ namespace Test
|
||||
// If an individual entry fails
|
||||
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(outputDirectory, entry.Key);
|
||||
entry.WriteToFile(tempFile);
|
||||
}
|
||||
@@ -314,28 +316,27 @@ namespace Test
|
||||
}
|
||||
|
||||
// InstallShield Archive V3 (Z)
|
||||
else if (ft == SupportedFileType.InstallShieldArchiveV3)
|
||||
else if (ft == WrapperType.InstallShieldArchiveV3)
|
||||
{
|
||||
// Build the InstallShield Archive V3 information
|
||||
Console.WriteLine("Extracting InstallShield Archive V3 contents");
|
||||
Console.WriteLine();
|
||||
|
||||
#if NET40_OR_GREATER || NETCOREAPP
|
||||
// If the cab file itself fails
|
||||
try
|
||||
{
|
||||
var archive = new InstallShieldArchiveV3(file);
|
||||
foreach (var cfile in archive.Files.Select(kvp => kvp.Value))
|
||||
foreach (var cfile in archive.Files)
|
||||
{
|
||||
// If an individual entry fails
|
||||
try
|
||||
{
|
||||
string tempFile = Path.Combine(outputDirectory, cfile.FullPath ?? string.Empty);
|
||||
string tempFile = Path.Combine(outputDirectory, cfile.Key);
|
||||
string? directoryName = Path.GetDirectoryName(tempFile);
|
||||
if (!string.IsNullOrEmpty(directoryName) && !Directory.Exists(directoryName))
|
||||
Directory.CreateDirectory(directoryName);
|
||||
|
||||
(byte[]? fileContents, string? error) = archive.Extract(cfile.FullPath ?? string.Empty);
|
||||
(byte[]? fileContents, string? error) = archive.Extract(cfile.Key);
|
||||
if (!string.IsNullOrEmpty(error))
|
||||
continue;
|
||||
|
||||
@@ -347,7 +348,7 @@ namespace Test
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine($"Something went wrong extracting InstallShield Archive V3 entry {cfile.Name}: {ex}");
|
||||
Console.WriteLine($"Something went wrong extracting InstallShield Archive V3 entry {cfile.Value.Name}: {ex}");
|
||||
Console.WriteLine();
|
||||
}
|
||||
}
|
||||
@@ -357,30 +358,32 @@ namespace Test
|
||||
Console.WriteLine($"Something went wrong extracting InstallShield Archive V3: {ex}");
|
||||
Console.WriteLine();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
// IS-CAB archive
|
||||
else if (ft == SupportedFileType.InstallShieldCAB)
|
||||
else if (ft == WrapperType.InstallShieldCAB)
|
||||
{
|
||||
// Build the archive information
|
||||
Console.WriteLine("Extracting IS-CAB contents");
|
||||
Console.WriteLine();
|
||||
|
||||
#if NET20 || NET35 || NET40
|
||||
Console.WriteLine("Extraction is not supported for this framework!");
|
||||
Console.WriteLine();
|
||||
#else
|
||||
// If the cab file itself fails
|
||||
try
|
||||
{
|
||||
var cabfile = UnshieldSharp.Cabinet.InstallShieldCabinet.Open(file);
|
||||
for (int i = 0; i < (cabfile?.FileCount ?? 0); i++)
|
||||
if (cabfile?.HeaderList == null)
|
||||
{
|
||||
Console.WriteLine("Something went wrong parsing IS-CAB archive");
|
||||
Console.WriteLine();
|
||||
return;
|
||||
}
|
||||
|
||||
for (int i = 0; i < cabfile!.HeaderList.FileCount; i++)
|
||||
{
|
||||
// If an individual entry fails
|
||||
try
|
||||
{
|
||||
string? filename = cabfile?.FileName(i);
|
||||
string? filename = cabfile.HeaderList.GetFileName(i);
|
||||
string tempFile;
|
||||
try
|
||||
{
|
||||
@@ -405,12 +408,11 @@ namespace Test
|
||||
Console.WriteLine($"Something went wrong extracting IS-CAB: {ex}");
|
||||
Console.WriteLine();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#if ((NETFRAMEWORK && !NET20 && !NET35 && !NET40) || NETCOREAPP) && WIN
|
||||
// Microsoft Cabinet archive
|
||||
else if (ft == SupportedFileType.MicrosoftCAB)
|
||||
else if (ft == WrapperType.MicrosoftCAB)
|
||||
{
|
||||
// Build the cabinet information
|
||||
Console.WriteLine("Extracting MS-CAB contents");
|
||||
@@ -454,7 +456,7 @@ namespace Test
|
||||
#endif
|
||||
|
||||
// Microsoft LZ / LZ32
|
||||
else if (ft == SupportedFileType.MicrosoftLZ)
|
||||
else if (ft == WrapperType.MicrosoftLZ)
|
||||
{
|
||||
// Build the Microsoft LZ / LZ32 information
|
||||
Console.WriteLine("Extracting Microsoft LZ / LZ32 contents");
|
||||
@@ -495,7 +497,7 @@ namespace Test
|
||||
|
||||
#if ((NETFRAMEWORK && !NET20 && !NET35 && !NET40) || NETCOREAPP) && WIN
|
||||
// MoPaQ (MPQ) archive
|
||||
else if (ft == SupportedFileType.MPQ)
|
||||
else if (ft == WrapperType.MoPaQ)
|
||||
{
|
||||
// Build the archive information
|
||||
Console.WriteLine("Extracting MoPaQ contents");
|
||||
@@ -555,7 +557,7 @@ namespace Test
|
||||
#endif
|
||||
|
||||
// PAK
|
||||
else if (ft == SupportedFileType.PAK)
|
||||
else if (ft == WrapperType.PAK)
|
||||
{
|
||||
// Build the archive information
|
||||
Console.WriteLine("Extracting PAK contents");
|
||||
@@ -582,7 +584,7 @@ namespace Test
|
||||
}
|
||||
|
||||
// PFF
|
||||
else if (ft == SupportedFileType.PFF)
|
||||
else if (ft == WrapperType.PFF)
|
||||
{
|
||||
// Build the archive information
|
||||
Console.WriteLine("Extracting PFF contents");
|
||||
@@ -609,7 +611,7 @@ namespace Test
|
||||
}
|
||||
|
||||
// PKZIP
|
||||
else if (ft == SupportedFileType.PKZIP)
|
||||
else if (ft == WrapperType.PKZIP)
|
||||
{
|
||||
// Build the archive information
|
||||
Console.WriteLine("Extracting PKZIP contents");
|
||||
@@ -628,10 +630,14 @@ namespace Test
|
||||
// If an individual entry fails
|
||||
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(outputDirectory, entry.Key);
|
||||
string? directoryName = Path.GetDirectoryName(tempFile);
|
||||
if (directoryName != null)
|
||||
@@ -654,7 +660,7 @@ namespace Test
|
||||
}
|
||||
|
||||
// Quantum
|
||||
else if (ft == SupportedFileType.Quantum)
|
||||
else if (ft == WrapperType.Quantum)
|
||||
{
|
||||
// Build the archive information
|
||||
Console.WriteLine("Extracting Quantum contents");
|
||||
@@ -681,7 +687,7 @@ namespace Test
|
||||
}
|
||||
|
||||
// RAR
|
||||
else if (ft == SupportedFileType.RAR)
|
||||
else if (ft == WrapperType.RAR)
|
||||
{
|
||||
// Build the archive information
|
||||
Console.WriteLine("Extracting RAR contents");
|
||||
@@ -700,10 +706,14 @@ namespace Test
|
||||
// If an individual entry fails
|
||||
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(outputDirectory, entry.Key);
|
||||
entry.WriteToFile(tempFile);
|
||||
}
|
||||
@@ -723,7 +733,7 @@ namespace Test
|
||||
}
|
||||
|
||||
// SGA
|
||||
else if (ft == SupportedFileType.SGA)
|
||||
else if (ft == WrapperType.SGA)
|
||||
{
|
||||
// Build the archive information
|
||||
Console.WriteLine("Extracting SGA contents");
|
||||
@@ -750,7 +760,7 @@ namespace Test
|
||||
}
|
||||
|
||||
// Tape Archive
|
||||
else if (ft == SupportedFileType.RAR)
|
||||
else if (ft == WrapperType.RAR)
|
||||
{
|
||||
// Build the archive information
|
||||
Console.WriteLine("Extracting Tape Archive contents");
|
||||
@@ -769,10 +779,14 @@ namespace Test
|
||||
// If an individual entry fails
|
||||
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(outputDirectory, entry.Key);
|
||||
entry.WriteToFile(tempFile);
|
||||
}
|
||||
@@ -792,7 +806,7 @@ namespace Test
|
||||
}
|
||||
|
||||
// VBSP
|
||||
else if (ft == SupportedFileType.VBSP)
|
||||
else if (ft == WrapperType.VBSP)
|
||||
{
|
||||
// Build the archive information
|
||||
Console.WriteLine("Extracting VBSP contents");
|
||||
@@ -819,7 +833,7 @@ namespace Test
|
||||
}
|
||||
|
||||
// VPK
|
||||
else if (ft == SupportedFileType.VPK)
|
||||
else if (ft == WrapperType.VPK)
|
||||
{
|
||||
// Build the archive information
|
||||
Console.WriteLine("Extracting VPK contents");
|
||||
@@ -846,7 +860,7 @@ namespace Test
|
||||
}
|
||||
|
||||
// WAD
|
||||
else if (ft == SupportedFileType.WAD)
|
||||
else if (ft == WrapperType.WAD)
|
||||
{
|
||||
// Build the archive information
|
||||
Console.WriteLine("Extracting WAD contents");
|
||||
@@ -873,7 +887,7 @@ namespace Test
|
||||
}
|
||||
|
||||
// xz
|
||||
else if (ft == SupportedFileType.RAR)
|
||||
else if (ft == WrapperType.RAR)
|
||||
{
|
||||
// Build the xz information
|
||||
Console.WriteLine("Extracting xz contents");
|
||||
@@ -900,7 +914,7 @@ namespace Test
|
||||
}
|
||||
|
||||
// XZP
|
||||
else if (ft == SupportedFileType.XZP)
|
||||
else if (ft == WrapperType.XZP)
|
||||
{
|
||||
// Build the archive information
|
||||
Console.WriteLine("Extracting XZP contents");
|
||||
|
||||
408
Test/Printer.cs
408
Test/Printer.cs
@@ -1,10 +1,8 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using BinaryObjectScanner.Utilities;
|
||||
using SabreTools.IO;
|
||||
using SabreTools.Serialization.Interfaces;
|
||||
using SabreTools.IO.Extensions;
|
||||
using SabreTools.Serialization.Wrappers;
|
||||
using SPrinter = SabreTools.Serialization.Printer;
|
||||
|
||||
namespace Test
|
||||
{
|
||||
@@ -27,11 +25,7 @@ namespace Test
|
||||
}
|
||||
else if (Directory.Exists(path))
|
||||
{
|
||||
#if NET20 || NET35
|
||||
foreach (string file in Directory.GetFiles(path, "*", SearchOption.AllDirectories))
|
||||
#else
|
||||
foreach (string file in Directory.EnumerateFiles(path, "*", SearchOption.AllDirectories))
|
||||
#endif
|
||||
foreach (string file in IOExtensions.SafeEnumerateFiles(path, "*", SearchOption.AllDirectories))
|
||||
{
|
||||
PrintFileInfo(file, json, debug);
|
||||
}
|
||||
@@ -49,39 +43,38 @@ namespace Test
|
||||
{
|
||||
Console.WriteLine($"Attempting to print info for {file}");
|
||||
|
||||
using Stream stream = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
|
||||
|
||||
// Read the first 8 bytes
|
||||
byte[]? magic = stream.ReadBytes(8);
|
||||
stream.Seek(0, SeekOrigin.Begin);
|
||||
|
||||
// Get the file type
|
||||
SupportedFileType ft = FileTypes.GetFileType(magic ?? []);
|
||||
if (ft == SupportedFileType.UNKNOWN)
|
||||
try
|
||||
{
|
||||
string extension = Path.GetExtension(file).TrimStart('.');
|
||||
ft = FileTypes.GetFileType(extension);
|
||||
}
|
||||
using Stream stream = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
|
||||
|
||||
// Print out the file format
|
||||
Console.WriteLine($"File format found: {ft}");
|
||||
// Read the first 8 bytes
|
||||
byte[]? magic = stream.ReadBytes(8);
|
||||
stream.Seek(0, SeekOrigin.Begin);
|
||||
|
||||
// Setup the wrapper to print
|
||||
var wrapper = WrapperFactory.CreateWrapper(ft, stream);
|
||||
// Get the file type
|
||||
WrapperType ft = WrapperFactory.GetFileType(magic ?? []);
|
||||
if (ft == WrapperType.UNKNOWN)
|
||||
{
|
||||
string extension = Path.GetExtension(file).TrimStart('.');
|
||||
ft = WrapperFactory.GetFileType(extension);
|
||||
}
|
||||
|
||||
// If we don't have a wrapper
|
||||
if (wrapper == null)
|
||||
{
|
||||
Console.WriteLine($"Either {ft} is not supported or something went wrong during parsing!");
|
||||
Console.WriteLine();
|
||||
return;
|
||||
}
|
||||
// Print out the file format
|
||||
Console.WriteLine($"File format found: {ft}");
|
||||
|
||||
// Print the wrapper name
|
||||
Console.WriteLine($"{wrapper.Description()} wrapper created successfully!");
|
||||
// Setup the wrapper to print
|
||||
var wrapper = WrapperFactory.CreateWrapper(ft, stream);
|
||||
|
||||
// Get the base info output name
|
||||
string filenameBase = $"info-{DateTime.Now:yyyy-MM-dd_HHmmss.ffff}";
|
||||
// If we don't have a wrapper
|
||||
if (wrapper == null)
|
||||
{
|
||||
Console.WriteLine($"Either {ft} is not supported or something went wrong during parsing!");
|
||||
Console.WriteLine();
|
||||
return;
|
||||
}
|
||||
|
||||
// Get the base info output name
|
||||
string filenameBase = $"info-{DateTime.Now:yyyy-MM-dd_HHmmss.ffff}";
|
||||
|
||||
#if NET6_0_OR_GREATER
|
||||
// If we have the JSON flag
|
||||
@@ -96,336 +89,25 @@ namespace Test
|
||||
jsw.WriteLine(serializedData);
|
||||
}
|
||||
#endif
|
||||
// Create the output data
|
||||
var builder = wrapper.PrettyPrint();
|
||||
Console.WriteLine(builder);
|
||||
|
||||
// Write the output data
|
||||
using var sw = new StreamWriter(File.OpenWrite($"{filenameBase}.txt"));
|
||||
sw.WriteLine(builder.ToString());
|
||||
}
|
||||
// Create the output data
|
||||
var builder = SPrinter.ExportStringBuilder(wrapper);
|
||||
if (builder == null)
|
||||
{
|
||||
Console.WriteLine("No item information could be generated");
|
||||
return;
|
||||
}
|
||||
|
||||
#region Printing Implementations
|
||||
|
||||
/// <summary>
|
||||
/// Export the item information as pretty-printed text
|
||||
/// </summary>
|
||||
private static StringBuilder PrettyPrint(this IWrapper wrapper)
|
||||
{
|
||||
return wrapper switch
|
||||
// Write the output data
|
||||
Console.WriteLine(builder);
|
||||
using var sw = new StreamWriter(File.OpenWrite($"{filenameBase}.txt"));
|
||||
sw.WriteLine(builder.ToString());
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
AACSMediaKeyBlock item => item.PrettyPrint(),
|
||||
BDPlusSVM item => item.PrettyPrint(),
|
||||
BFPK item => item.PrettyPrint(),
|
||||
BSP item => item.PrettyPrint(),
|
||||
CFB item => item.PrettyPrint(),
|
||||
CIA item => item.PrettyPrint(),
|
||||
GCF item => item.PrettyPrint(),
|
||||
InstallShieldCabinet item => item.PrettyPrint(),
|
||||
IRD item => item.PrettyPrint(),
|
||||
LinearExecutable item => item.PrettyPrint(),
|
||||
MicrosoftCabinet item => item.PrettyPrint(),
|
||||
MSDOS item => item.PrettyPrint(),
|
||||
N3DS item => item.PrettyPrint(),
|
||||
NCF item => item.PrettyPrint(),
|
||||
NewExecutable item => item.PrettyPrint(),
|
||||
Nitro item => item.PrettyPrint(),
|
||||
PAK item => item.PrettyPrint(),
|
||||
PFF item => item.PrettyPrint(),
|
||||
PlayJAudioFile item => item.PrettyPrint(),
|
||||
PortableExecutable item => item.PrettyPrint(),
|
||||
Quantum item => item.PrettyPrint(),
|
||||
SGA item => item.PrettyPrint(),
|
||||
VBSP item => item.PrettyPrint(),
|
||||
VPK item => item.PrettyPrint(),
|
||||
WAD item => item.PrettyPrint(),
|
||||
XeMID item => item.PrettyPrint(),
|
||||
XMID item => item.PrettyPrint(),
|
||||
XZP item => item.PrettyPrint(),
|
||||
_ => new StringBuilder(),
|
||||
};
|
||||
Console.WriteLine(debug ? ex : "[Exception opening file, please try again]");
|
||||
Console.WriteLine();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Export the item information as pretty-printed text
|
||||
/// </summary>
|
||||
private static StringBuilder PrettyPrint(this AACSMediaKeyBlock item)
|
||||
{
|
||||
var builder = new StringBuilder();
|
||||
SabreTools.Printing.AACSMediaKeyBlock.Print(builder, item.Model);
|
||||
return builder;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Export the item information as pretty-printed text
|
||||
/// </summary>
|
||||
private static StringBuilder PrettyPrint(this BDPlusSVM item)
|
||||
{
|
||||
var builder = new StringBuilder();
|
||||
SabreTools.Printing.BDPlusSVM.Print(builder, item.Model);
|
||||
return builder;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Export the item information as pretty-printed text
|
||||
/// </summary>
|
||||
private static StringBuilder PrettyPrint(this BFPK item)
|
||||
{
|
||||
var builder = new StringBuilder();
|
||||
SabreTools.Printing.BFPK.Print(builder, item.Model);
|
||||
return builder;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Export the item information as pretty-printed text
|
||||
/// </summary>
|
||||
private static StringBuilder PrettyPrint(this BSP item)
|
||||
{
|
||||
var builder = new StringBuilder();
|
||||
SabreTools.Printing.BSP.Print(builder, item.Model);
|
||||
return builder;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Export the item information as pretty-printed text
|
||||
/// </summary>
|
||||
private static StringBuilder PrettyPrint(this CFB item)
|
||||
{
|
||||
var builder = new StringBuilder();
|
||||
SabreTools.Printing.CFB.Print(builder, item.Model);
|
||||
return builder;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Export the item information as pretty-printed text
|
||||
/// </summary>
|
||||
private static StringBuilder PrettyPrint(this CIA item)
|
||||
{
|
||||
var builder = new StringBuilder();
|
||||
SabreTools.Printing.CIA.Print(builder, item.Model);
|
||||
return builder;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Export the item information as pretty-printed text
|
||||
/// </summary>
|
||||
private static StringBuilder PrettyPrint(this GCF item)
|
||||
{
|
||||
var builder = new StringBuilder();
|
||||
SabreTools.Printing.GCF.Print(builder, item.Model);
|
||||
return builder;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Export the item information as pretty-printed text
|
||||
/// </summary>
|
||||
private static StringBuilder PrettyPrint(this InstallShieldCabinet item)
|
||||
{
|
||||
var builder = new StringBuilder();
|
||||
SabreTools.Printing.InstallShieldCabinet.Print(builder, item.Model);
|
||||
return builder;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Export the item information as pretty-printed text
|
||||
/// </summary>
|
||||
private static StringBuilder PrettyPrint(this IRD item)
|
||||
{
|
||||
var builder = new StringBuilder();
|
||||
SabreTools.Printing.IRD.Print(builder, item.Model);
|
||||
return builder;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Export the item information as pretty-printed text
|
||||
/// </summary>
|
||||
private static StringBuilder PrettyPrint(this LinearExecutable item)
|
||||
{
|
||||
var builder = new StringBuilder();
|
||||
SabreTools.Printing.LinearExecutable.Print(builder, item.Model);
|
||||
return builder;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Export the item information as pretty-printed text
|
||||
/// </summary>
|
||||
private static StringBuilder PrettyPrint(this MicrosoftCabinet item)
|
||||
{
|
||||
var builder = new StringBuilder();
|
||||
SabreTools.Printing.MicrosoftCabinet.Print(builder, item.Model);
|
||||
return builder;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Export the item information as pretty-printed text
|
||||
/// </summary>
|
||||
private static StringBuilder PrettyPrint(this MSDOS item)
|
||||
{
|
||||
var builder = new StringBuilder();
|
||||
SabreTools.Printing.MSDOS.Print(builder, item.Model);
|
||||
return builder;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Export the item information as pretty-printed text
|
||||
/// </summary>
|
||||
private static StringBuilder PrettyPrint(this N3DS item)
|
||||
{
|
||||
var builder = new StringBuilder();
|
||||
SabreTools.Printing.N3DS.Print(builder, item.Model);
|
||||
return builder;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Export the item information as pretty-printed text
|
||||
/// </summary>
|
||||
private static StringBuilder PrettyPrint(this NCF item)
|
||||
{
|
||||
var builder = new StringBuilder();
|
||||
SabreTools.Printing.NCF.Print(builder, item.Model);
|
||||
return builder;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Export the item information as pretty-printed text
|
||||
/// </summary>
|
||||
private static StringBuilder PrettyPrint(this NewExecutable item)
|
||||
{
|
||||
var builder = new StringBuilder();
|
||||
SabreTools.Printing.NewExecutable.Print(builder, item.Model);
|
||||
return builder;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Export the item information as pretty-printed text
|
||||
/// </summary>
|
||||
private static StringBuilder PrettyPrint(this Nitro item)
|
||||
{
|
||||
var builder = new StringBuilder();
|
||||
SabreTools.Printing.Nitro.Print(builder, item.Model);
|
||||
return builder;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Export the item information as pretty-printed text
|
||||
/// </summary>
|
||||
private static StringBuilder PrettyPrint(this PAK item)
|
||||
{
|
||||
var builder = new StringBuilder();
|
||||
SabreTools.Printing.PAK.Print(builder, item.Model);
|
||||
return builder;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Export the item information as pretty-printed text
|
||||
/// </summary>
|
||||
private static StringBuilder PrettyPrint(this PFF item)
|
||||
{
|
||||
var builder = new StringBuilder();
|
||||
SabreTools.Printing.PFF.Print(builder, item.Model);
|
||||
return builder;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Export the item information as pretty-printed text
|
||||
/// </summary>
|
||||
private static StringBuilder PrettyPrint(this PlayJAudioFile item)
|
||||
{
|
||||
var builder = new StringBuilder();
|
||||
SabreTools.Printing.PlayJAudioFile.Print(builder, item.Model);
|
||||
return builder;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Export the item information as pretty-printed text
|
||||
/// </summary>
|
||||
private static StringBuilder PrettyPrint(this PortableExecutable item)
|
||||
{
|
||||
var builder = new StringBuilder();
|
||||
SabreTools.Printing.PortableExecutable.Print(builder, item.Model);
|
||||
return builder;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Export the item information as pretty-printed text
|
||||
/// </summary>
|
||||
private static StringBuilder PrettyPrint(this Quantum item)
|
||||
{
|
||||
var builder = new StringBuilder();
|
||||
SabreTools.Printing.Quantum.Print(builder, item.Model);
|
||||
return builder;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Export the item information as pretty-printed text
|
||||
/// </summary>
|
||||
private static StringBuilder PrettyPrint(this SGA item)
|
||||
{
|
||||
var builder = new StringBuilder();
|
||||
SabreTools.Printing.SGA.Print(builder, item.Model);
|
||||
return builder;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Export the item information as pretty-printed text
|
||||
/// </summary>
|
||||
private static StringBuilder PrettyPrint(this VBSP item)
|
||||
{
|
||||
var builder = new StringBuilder();
|
||||
SabreTools.Printing.VBSP.Print(builder, item.Model);
|
||||
return builder;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Export the item information as pretty-printed text
|
||||
/// </summary>
|
||||
private static StringBuilder PrettyPrint(this VPK item)
|
||||
{
|
||||
var builder = new StringBuilder();
|
||||
SabreTools.Printing.VPK.Print(builder, item.Model);
|
||||
return builder;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Export the item information as pretty-printed text
|
||||
/// </summary>
|
||||
private static StringBuilder PrettyPrint(this WAD item)
|
||||
{
|
||||
var builder = new StringBuilder();
|
||||
SabreTools.Printing.WAD.Print(builder, item.Model);
|
||||
return builder;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Export the item information as pretty-printed text
|
||||
/// </summary>
|
||||
private static StringBuilder PrettyPrint(this XeMID item)
|
||||
{
|
||||
var builder = new StringBuilder();
|
||||
SabreTools.Printing.XeMID.Print(builder, item.Model);
|
||||
return builder;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Export the item information as pretty-printed text
|
||||
/// </summary>
|
||||
private static StringBuilder PrettyPrint(this XMID item)
|
||||
{
|
||||
var builder = new StringBuilder();
|
||||
SabreTools.Printing.XMID.Print(builder, item.Model);
|
||||
return builder;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Export the item information as pretty-printed text
|
||||
/// </summary>
|
||||
private static StringBuilder PrettyPrint(this XZP item)
|
||||
{
|
||||
var builder = new StringBuilder();
|
||||
SabreTools.Printing.XZP.Print(builder, item.Model);
|
||||
return builder;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -7,7 +7,6 @@ using System.Collections.Concurrent;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using BinaryObjectScanner;
|
||||
using BinaryObjectScanner.Utilities;
|
||||
|
||||
namespace Test
|
||||
{
|
||||
|
||||
@@ -24,16 +24,15 @@
|
||||
<!-- Support for old .NET versions -->
|
||||
<ItemGroup Condition="!$(TargetFramework.StartsWith(`net2`)) AND !$(TargetFramework.StartsWith(`net3`))">
|
||||
<PackageReference Include="OpenMcdf" Version="2.3.1" />
|
||||
<PackageReference Include="UnshieldSharp" Version="1.7.2" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="SabreTools.Compression" Version="0.3.1" />
|
||||
<PackageReference Include="SabreTools.IO" Version="1.3.2" />
|
||||
<PackageReference Include="SabreTools.Compression" Version="0.5.1" />
|
||||
<PackageReference Include="SabreTools.IO" Version="1.4.8" />
|
||||
<PackageReference Include="SabreTools.Matching" Version="1.3.1" />
|
||||
<PackageReference Include="SabreTools.Models" Version="1.4.0" />
|
||||
<PackageReference Include="SabreTools.Printing" Version="1.3.2" />
|
||||
<PackageReference Include="SabreTools.Serialization" Version="1.4.0" />
|
||||
<PackageReference Include="SabreTools.Models" Version="1.4.5" />
|
||||
<PackageReference Include="SabreTools.Serialization" Version="1.6.1" />
|
||||
<PackageReference Include="UnshieldSharp" Version="1.8.2" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
Reference in New Issue
Block a user