Start rearranging things

This commit is contained in:
Matt Nadareski
2025-09-06 09:53:34 -04:00
parent e9c1e9b7e7
commit 43b3c72a02
16 changed files with 527 additions and 133 deletions

View File

@@ -15,7 +15,7 @@ namespace BinaryObjectScanner.Test
WrapperType.AACSMediaKeyBlock,
WrapperType.BDPlusSVM,
//WrapperType.CIA,
WrapperType.Executable,
//WrapperType.Executable,
WrapperType.LDSCRYPT,
//WrapperType.N3DS,
//WrapperType.Nitro,
@@ -63,7 +63,7 @@ namespace BinaryObjectScanner.Test
WrapperType.BZip2,
WrapperType.CFB,
//WrapperType.CIA,
WrapperType.Executable,
//WrapperType.Executable,
WrapperType.GCF,
WrapperType.GZip,
WrapperType.InstallShieldArchiveV3,

View File

@@ -0,0 +1,30 @@
using System.IO;
using BinaryObjectScanner.FileType;
using Xunit;
namespace BinaryObjectScanner.Test.FileType
{
public class LinearExecutableTests
{
[Fact]
public void DetectFile_EmptyString_Null()
{
string file = string.Empty;
var detectable = new LinearExecutable();
string? actual = detectable.Detect(file, includeDebug: false);
Assert.Null(actual);
}
[Fact]
public void DetectStream_EmptyStream_Null()
{
Stream? stream = new MemoryStream();
string file = string.Empty;
var detectable = new LinearExecutable();
string? actual = detectable.Detect(stream, file, includeDebug: false);
Assert.Null(actual);
}
}
}

View File

@@ -4,13 +4,13 @@ using Xunit;
namespace BinaryObjectScanner.Test.FileType
{
public class ExecutableTests
public class MSDOSTests
{
[Fact]
public void DetectFile_EmptyString_Null()
{
string file = string.Empty;
var detectable = new Executable();
var detectable = new MSDOS();
string? actual = detectable.Detect(file, includeDebug: false);
Assert.Null(actual);
@@ -21,7 +21,7 @@ namespace BinaryObjectScanner.Test.FileType
{
Stream? stream = new MemoryStream();
string file = string.Empty;
var detectable = new Executable();
var detectable = new MSDOS();
string? actual = detectable.Detect(stream, file, includeDebug: false);
Assert.Null(actual);

View File

@@ -0,0 +1,30 @@
using System.IO;
using BinaryObjectScanner.FileType;
using Xunit;
namespace BinaryObjectScanner.Test.FileType
{
public class NewExecutableTests
{
[Fact]
public void DetectFile_EmptyString_Null()
{
string file = string.Empty;
var detectable = new NewExecutable();
string? actual = detectable.Detect(file, includeDebug: false);
Assert.Null(actual);
}
[Fact]
public void DetectStream_EmptyStream_Null()
{
Stream? stream = new MemoryStream();
string file = string.Empty;
var detectable = new NewExecutable();
string? actual = detectable.Detect(stream, file, includeDebug: false);
Assert.Null(actual);
}
}
}

View File

@@ -0,0 +1,30 @@
using System.IO;
using BinaryObjectScanner.FileType;
using Xunit;
namespace BinaryObjectScanner.Test.FileType
{
public class PortableExecutableTests
{
[Fact]
public void DetectFile_EmptyString_Null()
{
string file = string.Empty;
var detectable = new PortableExecutable();
string? actual = detectable.Detect(file, includeDebug: false);
Assert.Null(actual);
}
[Fact]
public void DetectStream_EmptyStream_Null()
{
Stream? stream = new MemoryStream();
string file = string.Empty;
var detectable = new PortableExecutable();
string? actual = detectable.Detect(stream, file, includeDebug: false);
Assert.Null(actual);
}
}
}

View File

@@ -1,4 +1,4 @@
using BinaryObjectScanner.Interfaces;
using SabreTools.Serialization.Interfaces;
using SabreTools.Serialization.Wrappers;
namespace BinaryObjectScanner
@@ -8,18 +8,41 @@ namespace BinaryObjectScanner
/// <summary>
/// Create an instance of a detectable based on file type
/// </summary>
public static IDetectable? CreateDetectable(WrapperType fileType)
public static Interfaces.IDetectable? CreateDetectable(WrapperType fileType)
=> CreateDetectable(fileType, null);
/// <summary>
/// Create an instance of a detectable based on file type
/// </summary>
public static Interfaces.IDetectable? CreateDetectable(WrapperType fileType, IWrapper? wrapper)
{
// Use the wrapper before the type
switch (wrapper)
{
case AACSMediaKeyBlock: return new FileType.AACSMediaKeyBlock();
case BDPlusSVM: return new FileType.BDPlusSVM();
// case CIA => new FileType.CIA(),
case LinearExecutable: return new FileType.LinearExecutable();
case MSDOS: return new FileType.MSDOS();
// case N3DS: return new FileType.N3DS();
case NewExecutable: return new FileType.NewExecutable();
case PlayJAudioFile: return new FileType.PLJ();
case PortableExecutable: return new FileType.PortableExecutable();
}
// Fall back on the file type for types not implemented in Serialization
return fileType switch
{
WrapperType.AACSMediaKeyBlock => new FileType.AACSMediaKeyBlock(),
WrapperType.BDPlusSVM => new FileType.BDPlusSVM(),
//WrapperType.CIA => new FileType.CIA(),
WrapperType.Executable => new FileType.Executable(),
// WrapperType.CIA => new FileType.CIA(),
WrapperType.LDSCRYPT => new FileType.LDSCRYPT(),
//WrapperType.N3DS => new FileType.N3DS(),
//WrapperType.Nitro => new FileType.Nitro(),
// WrapperType.LinearExecutable => new FileType.LinearExecutable(),
// WrapperType.MSDOS => new FileType.MSDOS(),
// WrapperType.N3DS => new FileType.N3DS(),
// WrapperType.NewExecutable => new FileType.NewExecutable(),
WrapperType.PlayJAudioFile => new FileType.PLJ(),
// WrapperType.PortableExecutable => new FileType.PortableExecutable(),
WrapperType.RealArcadeInstaller => new FileType.RealArcadeInstaller(),
WrapperType.RealArcadeMezzanine => new FileType.RealArcadeMezzanine(),
WrapperType.SFFS => new FileType.SFFS(),
@@ -31,33 +54,84 @@ namespace BinaryObjectScanner
/// <summary>
/// Create an instance of an extractable based on file type
/// </summary>
public static IExtractable? CreateExtractable(WrapperType fileType)
public static Interfaces.IExtractable? CreateExtractable(WrapperType fileType)
=> CreateExtractable(fileType, null);
/// <summary>
/// Create an instance of an extractable based on file type
/// </summary>
public static Interfaces.IExtractable? CreateExtractable(WrapperType fileType, IWrapper? wrapper)
{
// Use the wrapper before the type
switch (wrapper)
{
case BFPK: return new FileType.BFPK();
case BSP: return new FileType.BSP();
case BZip2: return new FileType.BZip2();
case CFB: return new FileType.CFB();
// case CIA => new FileType.CIA(),
case GCF: return new FileType.GCF();
case GZip: return new FileType.GZip();
case InstallShieldArchiveV3: return new FileType.InstallShieldArchiveV3();
case InstallShieldCabinet: return new FileType.InstallShieldCAB();
case LinearExecutable: return new FileType.LinearExecutable();
case LZKWAJ: return new FileType.LZKWAJ();
case LZQBasic: return new FileType.LZQBasic();
case LZSZDD: return new FileType.LZSZDD();
case MicrosoftCabinet: return new FileType.MicrosoftCAB();
case MoPaQ: return new FileType.MPQ();
case MSDOS: return new FileType.MSDOS();
// case N3DS: return new FileType.N3DS();
// case NCF: return new FileType.NCF();
case NewExecutable: return new FileType.NewExecutable();
// case Nitro: return new FileType.Nitro();
case PAK: return new FileType.PAK();
case PFF: return new FileType.PFF();
case PKZIP: return new FileType.PKZIP();
// case PlayJAudioFile: return new FileType.PLJ();
case PortableExecutable: return new FileType.PortableExecutable();
case Quantum: return new FileType.Quantum();
case RAR: return new FileType.RAR();
case SevenZip: return new FileType.SevenZip();
case SGA: return new FileType.SGA();
case TapeArchive: return new FileType.TapeArchive();
case VBSP: return new FileType.VBSP();
case VPK: return new FileType.VPK();
case WAD3: return new FileType.WAD3();
case XZ: return new FileType.XZ();
case XZP: return new FileType.XZP();
}
// Fall back on the file type for types not implemented in Serialization
return fileType switch
{
WrapperType.BFPK => new FileType.BFPK(),
WrapperType.BSP => new FileType.BSP(),
WrapperType.BZip2 => new FileType.BZip2(),
WrapperType.CFB => new FileType.CFB(),
//WrapperType.CIA => new FileType.CIA(),
WrapperType.Executable => new FileType.Executable(),
// WrapperType.CIA => new FileType.CIA(),
// WrapperType.Executable => new FileType.Executable(),
WrapperType.GCF => new FileType.GCF(),
WrapperType.GZip => new FileType.GZip(),
WrapperType.InstallShieldArchiveV3 => new FileType.InstallShieldArchiveV3(),
WrapperType.InstallShieldCAB => new FileType.InstallShieldCAB(),
// WrapperType.LinearExecutable => new FileType.LinearExecutable(),
WrapperType.LZKWAJ => new FileType.LZKWAJ(),
WrapperType.LZQBasic => new FileType.LZQBasic(),
WrapperType.LZSZDD => new FileType.LZSZDD(),
WrapperType.MicrosoftCAB => new FileType.MicrosoftCAB(),
WrapperType.MoPaQ => new FileType.MPQ(),
//WrapperType.N3DS => new FileType.N3DS(),
//WrapperType.NCF => new FileType.NCF(),
//WrapperType.Nitro => new FileType.Nitro(),
// WrapperType.MSDOS => new FileType.MSDOS(),
// WrapperType.N3DS => new FileType.N3DS(),
// WrapperType.NCF => new FileType.NCF(),
// WrapperType.NewExecutable => new FileType.NewExecutable(),
// WrapperType.Nitro => new FileType.Nitro(),
WrapperType.PAK => new FileType.PAK(),
WrapperType.PFF => new FileType.PFF(),
WrapperType.PKZIP => new FileType.PKZIP(),
//WrapperType.PlayJAudioFile => new FileType.PLJ(),
//WrapperType.Quantum => new FileType.Quantum(),
// WrapperType.PlayJAudioFile => new FileType.PLJ(),
// WrapperType.PortableExecutable => new FileType.PortableExecutable(),
// WrapperType.Quantum => new FileType.Quantum(),
WrapperType.RAR => new FileType.RAR(),
WrapperType.SevenZip => new FileType.SevenZip(),
WrapperType.SFFS => new FileType.SFFS(),

View File

@@ -7,7 +7,7 @@ namespace BinaryObjectScanner.FileType
/// <summary>
/// AACS media key block
/// </summary>
public class AACSMediaKeyBlock : IDetectable
public class AACSMediaKeyBlock : IDetectable<SabreTools.Serialization.Wrappers.AACSMediaKeyBlock>
{
/// <inheritdoc/>
public string? Detect(string file, bool includeDebug)

View File

@@ -6,7 +6,7 @@ namespace BinaryObjectScanner.FileType
/// <summary>
/// BD+ SVM
/// </summary>
public class BDPlusSVM : IDetectable
public class BDPlusSVM : IDetectable<SabreTools.Serialization.Wrappers.BDPlusSVM>
{
/// <inheritdoc/>
public string? Detect(string file, bool includeDebug)

View File

@@ -11,7 +11,8 @@ namespace BinaryObjectScanner.FileType
/// <summary>
/// Executable or library
/// </summary>
public class Executable : IDetectable, IExtractable
public abstract class Executable<T> : IDetectable, IExtractable
where T : WrapperBase
{
/// <inheritdoc/>
public string? Detect(string file, bool includeDebug)
@@ -24,74 +25,7 @@ namespace BinaryObjectScanner.FileType
}
/// <inheritdoc/>
public string? Detect(Stream stream, string file, bool includeDebug)
{
// Create the output dictionary
var protections = new ProtectionDictionary();
// Try to create a wrapper for the proper executable type
SabreTools.Serialization.Interfaces.IWrapper? wrapper;
try
{
wrapper = WrapperFactory.CreateExecutableWrapper(stream);
if (wrapper == null)
return null;
}
catch (Exception ex)
{
if (includeDebug) Console.Error.WriteLine(ex);
return null;
}
// Only use generic content checks if we're in debug mode
if (includeDebug)
{
var subProtections = RunContentChecks(file, stream, includeDebug);
protections.Append(file, subProtections.Values);
}
if (wrapper is MSDOS mz)
{
// Standard checks
var subProtections
= RunExecutableChecks(file, mz, StaticChecks.MSDOSExecutableCheckClasses, includeDebug);
protections.Append(file, subProtections.Values);
}
else if (wrapper is LinearExecutable lex)
{
// Standard checks
var subProtections
= RunExecutableChecks(file, lex, StaticChecks.LinearExecutableCheckClasses, includeDebug);
protections.Append(file, subProtections.Values);
}
else if (wrapper is NewExecutable nex)
{
// Standard checks
var subProtections
= RunExecutableChecks(file, nex, StaticChecks.NewExecutableCheckClasses, includeDebug);
protections.Append(file, subProtections.Values);
}
else if (wrapper is PortableExecutable pex)
{
// Standard checks
var subProtections
= RunExecutableChecks(file, pex, StaticChecks.PortableExecutableCheckClasses, includeDebug);
protections.Append(file, subProtections.Values);
}
// If there are no protections
if (protections.Count == 0)
return null;
// Create the internal list
var protectionList = new List<string>();
foreach (string key in protections.Keys)
{
protectionList.AddRange(protections[key]);
}
return string.Join(";", [.. protectionList]);
}
public abstract string? Detect(Stream stream, string file, bool includeDebug);
/// <inheritdoc/>
public bool Extract(string file, string outDir, bool includeDebug)
@@ -104,41 +38,7 @@ namespace BinaryObjectScanner.FileType
}
/// <inheritdoc/>
public bool Extract(Stream? stream, string file, string outDir, bool includeDebug)
{
// Create the wrapper
var wrapper = WrapperFactory.CreateExecutableWrapper(stream);
if (wrapper == null)
return false;
// Extract all files
bool extractAny = false;
Directory.CreateDirectory(outDir);
if (wrapper is PortableExecutable pex)
{
if (new Packer.CExe().CheckExecutable(file, pex, includeDebug) != null)
extractAny |= pex.ExtractCExe(outDir, includeDebug);
if (new Packer.EmbeddedFile().CheckExecutable(file, pex, includeDebug) != null)
{
extractAny |= pex.ExtractFromOverlay(outDir, includeDebug);
extractAny |= pex.ExtractFromResources(outDir, includeDebug);
}
if (new Packer.WiseInstaller().CheckExecutable(file, pex, includeDebug) != null)
extractAny |= pex.ExtractWise(outDir, includeDebug);
}
else if (wrapper is NewExecutable nex)
{
if (new Packer.EmbeddedFile().CheckExecutable(file, nex, includeDebug) != null)
extractAny |= nex.ExtractFromOverlay(outDir, includeDebug);
if (new Packer.WiseInstaller().CheckExecutable(file, nex, includeDebug) != null)
extractAny |= nex.ExtractWise(outDir, includeDebug);
}
return extractAny;
}
public abstract bool Extract(Stream? stream, string file, string outDir, bool includeDebug);
#region Check Runners
@@ -149,7 +49,7 @@ namespace BinaryObjectScanner.FileType
/// <param name="stream">Stream to scan the contents of</param>
/// <param name="includeDebug">True to include debug data, false otherwise</param>
/// <returns>Set of protections in file, empty on error</returns>
private static IDictionary<IContentCheck, string> RunContentChecks(string? file, Stream stream, bool includeDebug)
protected IDictionary<IContentCheck, string> RunContentChecks(string? file, Stream stream, bool includeDebug)
{
// Create the output dictionary
var protections = new CheckDictionary<IContentCheck>();
@@ -202,8 +102,7 @@ namespace BinaryObjectScanner.FileType
/// <param name="scanner">Scanner for handling recursive protections</param>
/// <param name="includeDebug">True to include debug data, false otherwise</param>
/// <returns>Set of protections in file, empty on error</returns>
private static IDictionary<U, string> RunExecutableChecks<T, U>(string file, T exe, List<U> checks, bool includeDebug)
where T : WrapperBase
protected IDictionary<U, string> RunExecutableChecks<U>(string file, T exe, List<U> checks, bool includeDebug)
where U : IExecutableCheck<T>
{
// Create the output dictionary

View File

@@ -0,0 +1,67 @@
using System;
using System.Collections.Generic;
using System.IO;
using BinaryObjectScanner.Data;
using SabreTools.Serialization.Wrappers;
namespace BinaryObjectScanner.FileType
{
/// <summary>
/// Linear executable (LE/LX)
/// </summary>
public class LinearExecutable : Executable<SabreTools.Serialization.Wrappers.LinearExecutable>
{
/// <inheritdoc/>
public override string? Detect(Stream stream, string file, bool includeDebug)
{
// Create the output dictionary
var protections = new ProtectionDictionary();
// Try to create a wrapper for the proper executable type
SabreTools.Serialization.Interfaces.IWrapper? wrapper;
try
{
wrapper = WrapperFactory.CreateExecutableWrapper(stream);
if (wrapper == null)
return null;
}
catch (Exception ex)
{
if (includeDebug) Console.Error.WriteLine(ex);
return null;
}
// Only use generic content checks if we're in debug mode
if (includeDebug)
{
var contentProtections = RunContentChecks(file, stream, includeDebug);
protections.Append(file, contentProtections.Values);
}
// Only handle LE/LX
if (wrapper is not SabreTools.Serialization.Wrappers.LinearExecutable lex)
return null;
// Standard checks
var subProtections
= RunExecutableChecks(file, lex, StaticChecks.LinearExecutableCheckClasses, includeDebug);
protections.Append(file, subProtections.Values);
// If there are no protections
if (protections.Count == 0)
return null;
// Create the internal list
var protectionList = new List<string>();
foreach (string key in protections.Keys)
{
protectionList.AddRange(protections[key]);
}
return string.Join(";", [.. protectionList]);
}
/// <inheritdoc/>
public override bool Extract(Stream? stream, string file, string outDir, bool includeDebug) => false;
}
}

View File

@@ -0,0 +1,67 @@
using System;
using System.Collections.Generic;
using System.IO;
using BinaryObjectScanner.Data;
using SabreTools.Serialization.Wrappers;
namespace BinaryObjectScanner.FileType
{
/// <summary>
/// MS-DOS executable (MZ)
/// </summary>
public class MSDOS : Executable<SabreTools.Serialization.Wrappers.MSDOS>
{
/// <inheritdoc/>
public override string? Detect(Stream stream, string file, bool includeDebug)
{
// Create the output dictionary
var protections = new ProtectionDictionary();
// Try to create a wrapper for the proper executable type
SabreTools.Serialization.Interfaces.IWrapper? wrapper;
try
{
wrapper = WrapperFactory.CreateExecutableWrapper(stream);
if (wrapper == null)
return null;
}
catch (Exception ex)
{
if (includeDebug) Console.Error.WriteLine(ex);
return null;
}
// Only use generic content checks if we're in debug mode
if (includeDebug)
{
var contentProtections = RunContentChecks(file, stream, includeDebug);
protections.Append(file, contentProtections.Values);
}
// Only handle MS-DOS
if (wrapper is not SabreTools.Serialization.Wrappers.MSDOS mz)
return null;
// Standard checks
var subProtections
= RunExecutableChecks(file, mz, StaticChecks.MSDOSExecutableCheckClasses, includeDebug);
protections.Append(file, subProtections.Values);
// If there are no protections
if (protections.Count == 0)
return null;
// Create the internal list
var protectionList = new List<string>();
foreach (string key in protections.Keys)
{
protectionList.AddRange(protections[key]);
}
return string.Join(";", [.. protectionList]);
}
/// <inheritdoc/>
public override bool Extract(Stream? stream, string file, string outDir, bool includeDebug) => false;
}
}

View File

@@ -0,0 +1,90 @@
using System;
using System.Collections.Generic;
using System.IO;
using BinaryObjectScanner.Data;
using SabreTools.Serialization.Wrappers;
namespace BinaryObjectScanner.FileType
{
/// <summary>
/// New executable (NE)
/// </summary>
public class NewExecutable : Executable<SabreTools.Serialization.Wrappers.NewExecutable>
{
/// <inheritdoc/>
public override string? Detect(Stream stream, string file, bool includeDebug)
{
// Create the output dictionary
var protections = new ProtectionDictionary();
// Try to create a wrapper for the proper executable type
SabreTools.Serialization.Interfaces.IWrapper? wrapper;
try
{
wrapper = WrapperFactory.CreateExecutableWrapper(stream);
if (wrapper == null)
return null;
}
catch (Exception ex)
{
if (includeDebug) Console.Error.WriteLine(ex);
return null;
}
// Only use generic content checks if we're in debug mode
if (includeDebug)
{
var contentProtections = RunContentChecks(file, stream, includeDebug);
protections.Append(file, contentProtections.Values);
}
// Only handle NE
if (wrapper is not SabreTools.Serialization.Wrappers.NewExecutable nex)
return null;
// Standard checks
var subProtections
= RunExecutableChecks(file, nex, StaticChecks.NewExecutableCheckClasses, includeDebug);
protections.Append(file, subProtections.Values);
// If there are no protections
if (protections.Count == 0)
return null;
// Create the internal list
var protectionList = new List<string>();
foreach (string key in protections.Keys)
{
protectionList.AddRange(protections[key]);
}
return string.Join(";", [.. protectionList]);
}
/// <inheritdoc/>
public override bool Extract(Stream? stream, string file, string outDir, bool includeDebug)
{
// Create the wrapper
var wrapper = WrapperFactory.CreateExecutableWrapper(stream);
if (wrapper == null)
return false;
// Only handle NE
if (wrapper is not SabreTools.Serialization.Wrappers.NewExecutable nex)
return false;
// Create the output directory
Directory.CreateDirectory(outDir);
// Extract all files
bool extractAny = false;
if (new Packer.EmbeddedFile().CheckExecutable(file, nex, includeDebug) != null)
extractAny |= nex.ExtractFromOverlay(outDir, includeDebug);
if (new Packer.WiseInstaller().CheckExecutable(file, nex, includeDebug) != null)
extractAny |= nex.ExtractWise(outDir, includeDebug);
return extractAny;
}
}
}

View File

@@ -8,7 +8,7 @@ namespace BinaryObjectScanner.FileType
/// <summary>
/// PlayJ audio file
/// </summary>
public class PLJ : IDetectable
public class PLJ : IDetectable<SabreTools.Serialization.Wrappers.PlayJAudioFile>
{
/// <inheritdoc/>
public string? Detect(string file, bool includeDebug)

View File

@@ -0,0 +1,96 @@
using System;
using System.Collections.Generic;
using System.IO;
using BinaryObjectScanner.Data;
using SabreTools.Serialization.Wrappers;
namespace BinaryObjectScanner.FileType
{
/// <summary>
/// Portable executable (PE)
/// </summary>
public class PortableExecutable : Executable<SabreTools.Serialization.Wrappers.PortableExecutable>
{
/// <inheritdoc/>
public override string? Detect(Stream stream, string file, bool includeDebug)
{
// Create the output dictionary
var protections = new ProtectionDictionary();
// Try to create a wrapper for the proper executable type
SabreTools.Serialization.Interfaces.IWrapper? wrapper;
try
{
wrapper = WrapperFactory.CreateExecutableWrapper(stream);
if (wrapper == null)
return null;
}
catch (Exception ex)
{
if (includeDebug) Console.Error.WriteLine(ex);
return null;
}
// Only use generic content checks if we're in debug mode
if (includeDebug)
{
var contentProtections = RunContentChecks(file, stream, includeDebug);
protections.Append(file, contentProtections.Values);
}
// Only handle PE
if (wrapper is not SabreTools.Serialization.Wrappers.PortableExecutable pex)
return null;
// Standard checks
var subProtections
= RunExecutableChecks(file, pex, StaticChecks.PortableExecutableCheckClasses, includeDebug);
protections.Append(file, subProtections.Values);
// If there are no protections
if (protections.Count == 0)
return null;
// Create the internal list
var protectionList = new List<string>();
foreach (string key in protections.Keys)
{
protectionList.AddRange(protections[key]);
}
return string.Join(";", [.. protectionList]);
}
/// <inheritdoc/>
public override bool Extract(Stream? stream, string file, string outDir, bool includeDebug)
{
// Create the wrapper
var wrapper = WrapperFactory.CreateExecutableWrapper(stream);
if (wrapper == null)
return false;
// Only handle PE
if (wrapper is not SabreTools.Serialization.Wrappers.PortableExecutable pex)
return false;
// Create the output directory
Directory.CreateDirectory(outDir);
// Extract all files
bool extractAny = false;
if (new Packer.CExe().CheckExecutable(file, pex, includeDebug) != null)
extractAny |= pex.ExtractCExe(outDir, includeDebug);
if (new Packer.EmbeddedFile().CheckExecutable(file, pex, includeDebug) != null)
{
extractAny |= pex.ExtractFromOverlay(outDir, includeDebug);
extractAny |= pex.ExtractFromResources(outDir, includeDebug);
}
if (new Packer.WiseInstaller().CheckExecutable(file, pex, includeDebug) != null)
extractAny |= pex.ExtractWise(outDir, includeDebug);
return extractAny;
}
}
}

View File

@@ -0,0 +1,9 @@
using SabreTools.Serialization.Interfaces;
namespace BinaryObjectScanner.Interfaces
{
/// <summary>
/// Mark a file type as being able to be detected
/// </summary>
public interface IDetectable<T> : IDetectable where T : IWrapper { }
}

View File

@@ -2,7 +2,6 @@
using System.Collections.Generic;
using System.IO;
using BinaryObjectScanner.Data;
using BinaryObjectScanner.FileType;
using BinaryObjectScanner.Interfaces;
using SabreTools.IO.Extensions;
using SabreTools.Serialization.Wrappers;
@@ -268,10 +267,13 @@ namespace BinaryObjectScanner
if (fileType == WrapperType.UNKNOWN)
return [];
// Get the wrapper, if possible
var wrapper = WrapperFactory.CreateWrapper(fileType, stream);
#region Non-Archive File Types
// Create a detectable for the given file type
var detectable = Factory.CreateDetectable(fileType);
var detectable = Factory.CreateDetectable(fileType, wrapper);
// If we're scanning file contents
if (detectable != null && _options.ScanContents)
@@ -285,10 +287,10 @@ namespace BinaryObjectScanner
#region Archive File Types
// Create an extractable for the given file type
var extractable = Factory.CreateExtractable(fileType);
var extractable = Factory.CreateExtractable(fileType, wrapper);
// If we're scanning archives
if (extractable != null && (extractable is Executable || _options.ScanArchives))
if (extractable != null && _options.ScanArchives)
{
// If the extractable file itself fails
try