Move most detectables to new interface

This commit is contained in:
Matt Nadareski
2023-03-13 16:06:45 -04:00
parent d439ba9592
commit c43353d126
14 changed files with 271 additions and 276 deletions

View File

@@ -0,0 +1,51 @@
using System;
using System.IO;
using System.Linq;
using BinaryObjectScanner.Interfaces;
namespace BinaryObjectScanner.FileType
{
/// <summary>
/// AACS media key block
/// </summary>
public class AACSMediaKeyBlock : 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.Read))
{
return Detect(fs, file, includeDebug);
}
}
/// <inheritdoc/>
public string Detect(Stream stream, string file, bool includeDebug)
{
// If the MKB file itself fails
try
{
// Create the wrapper
Wrappers.AACSMediaKeyBlock mkb = Wrappers.AACSMediaKeyBlock.Create(stream);
if (mkb == null)
return null;
// Derive the version, if possible
var typeAndVersion = mkb.Records.FirstOrDefault(r => r.RecordType == Models.AACS.RecordType.TypeAndVersion);
if (typeAndVersion == null)
return "AACS (Unknown Version)";
else
return $"AACS {(typeAndVersion as Models.AACS.TypeAndVersionRecord).VersionNumber}";
}
catch (Exception ex)
{
if (includeDebug) Console.WriteLine(ex);
}
return null;
}
}
}

View File

@@ -0,0 +1,49 @@
using System;
using System.IO;
using BinaryObjectScanner.Interfaces;
namespace BinaryObjectScanner.FileType
{
/// <summary>
/// BD+ SVM
/// </summary>
public class BDPlusSVM : 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.Read))
{
return Detect(fs, file, includeDebug);
}
}
/// <inheritdoc/>
public string Detect(Stream stream, string file, bool includeDebug)
{
// If the BD+ file itself fails
try
{
// Create the wrapper
Wrappers.BDPlusSVM svm = Wrappers.BDPlusSVM.Create(stream);
if (svm == null)
return null;
// Format the date
string date = $"{svm.Year:0000}/{svm.Month:00}/{svm.Day:00}";
// Return the formatted value
return $"BD+ {date}";
}
catch (Exception ex)
{
if (includeDebug) Console.WriteLine(ex);
}
return null;
}
}
}

View File

@@ -22,6 +22,7 @@
<ItemGroup>
<ProjectReference Include="..\BinaryObjectScanner.Interfaces\BinaryObjectScanner.Interfaces.csproj" />
<ProjectReference Include="..\BinaryObjectScanner.Matching\BinaryObjectScanner.Matching.csproj" />
<ProjectReference Include="..\BinaryObjectScanner.Wrappers\BinaryObjectScanner.Wrappers.csproj" />
</ItemGroup>

View File

@@ -0,0 +1,44 @@
using System;
using System.IO;
using BinaryObjectScanner.Interfaces;
using BinaryObjectScanner.Matching;
namespace BinaryObjectScanner.FileType
{
/// <summary>
/// Link Data Security encrypted file
/// </summary>
public class LDSCRYPT : 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.Read))
{
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);
if (magic.StartsWith(new byte?[] { 0x4C, 0x44, 0x53, 0x43, 0x52, 0x59, 0x50, 0x54 }))
return "Link Data Security encrypted file";
}
catch (Exception ex)
{
if (includeDebug) Console.WriteLine(ex);
}
return null;
}
}
}

View File

@@ -0,0 +1,44 @@
using System;
using System.IO;
using BinaryObjectScanner.Interfaces;
using BinaryObjectScanner.Matching;
namespace BinaryObjectScanner.FileType
{
/// <summary>
/// PlayJ audio file
/// </summary>
public class PLJ : 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.Read))
{
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);
if (magic.StartsWith(new byte?[] { 0xFF, 0x9D, 0x53, 0x4B }))
return "PlayJ Audio File";
}
catch (Exception ex)
{
if (includeDebug) Console.WriteLine(ex);
}
return null;
}
}
}

View File

@@ -1,18 +1,47 @@
using System;
using System.Collections.Concurrent;
using System.IO;
using BurnOutSharp.Interfaces;
using BinaryObjectScanner.Interfaces;
using static BinaryObjectScanner.Utilities.Dictionary;
using BinaryObjectScanner.Matching;
namespace BurnOutSharp.FileType
namespace BinaryObjectScanner.FileType
{
/// <summary>
/// StarForce Filesystem file
/// </summary>
/// <see href="https://forum.xentax.com/viewtopic.php?f=21&t=2084"/>
public class SFFS : IExtractable, IScannable
public class SFFS : IExtractable, 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.Read))
{
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);
if (magic.StartsWith(new byte?[] { 0x53, 0x46, 0x46, 0x53 }))
return "StarForce Filesystem Container";
}
catch (Exception ex)
{
if (includeDebug) Console.WriteLine(ex);
}
return null;
}
/// <inheritdoc/>
public string Extract(string file, bool includeDebug)
{
@@ -30,40 +59,5 @@ namespace BurnOutSharp.FileType
{
return null;
}
/// <inheritdoc/>
public ConcurrentDictionary<string, ConcurrentQueue<string>> Scan(Scanner scanner, string file)
{
if (!File.Exists(file))
return null;
using (var fs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.Read))
{
return Scan(scanner, fs, file);
}
}
/// <inheritdoc/>
public ConcurrentDictionary<string, ConcurrentQueue<string>> Scan(Scanner scanner, Stream stream, string file)
{
var protections = new ConcurrentDictionary<string, ConcurrentQueue<string>>();
try
{
byte[] magic = new byte[16];
stream.Read(magic, 0, 16);
if (Tools.FileTypeTools.GetFileType(magic) == SupportedFileType.SFFS)
{
AppendToDictionary(protections, file, "StarForce Filesystem Container");
return protections;
}
}
catch (Exception ex)
{
if (scanner.IncludeDebug) Console.WriteLine(ex);
}
return null;
}
}
}

View File

@@ -1,57 +0,0 @@
using System;
using System.Collections.Concurrent;
using System.IO;
using System.Linq;
using BurnOutSharp.Interfaces;
namespace BurnOutSharp.FileType
{
/// <summary>
/// AACS media key block
/// </summary>
public class AACSMediaKeyBlock : IScannable
{
/// <inheritdoc/>
public ConcurrentDictionary<string, ConcurrentQueue<string>> Scan(Scanner scanner, string file)
{
if (!File.Exists(file))
return null;
using (var fs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.Read))
{
return Scan(scanner, fs, file);
}
}
/// <inheritdoc/>
public ConcurrentDictionary<string, ConcurrentQueue<string>> Scan(Scanner scanner, Stream stream, string file)
{
// If the MKB file itself fails
try
{
// Create the wrapper
BinaryObjectScanner.Wrappers.AACSMediaKeyBlock mkb = BinaryObjectScanner.Wrappers.AACSMediaKeyBlock.Create(stream);
if (mkb == null)
return null;
// Setup the output
var protections = new ConcurrentDictionary<string, ConcurrentQueue<string>>();
protections[file] = new ConcurrentQueue<string>();
var typeAndVersion = mkb.Records.FirstOrDefault(r => r.RecordType == BinaryObjectScanner.Models.AACS.RecordType.TypeAndVersion);
if (typeAndVersion == null)
protections[file].Enqueue("AACS (Unknown Version)");
else
protections[file].Enqueue($"AACS {(typeAndVersion as BinaryObjectScanner.Models.AACS.TypeAndVersionRecord).VersionNumber}");
return protections;
}
catch (Exception ex)
{
if (scanner.IncludeDebug) Console.WriteLine(ex);
}
return null;
}
}
}

View File

@@ -1,55 +0,0 @@
using System;
using System.Collections.Concurrent;
using System.IO;
using BurnOutSharp.Interfaces;
namespace BurnOutSharp.FileType
{
/// <summary>
/// BD+ SVM
/// </summary>
public class BDPlusSVM : IScannable
{
/// <inheritdoc/>
public ConcurrentDictionary<string, ConcurrentQueue<string>> Scan(Scanner scanner, string file)
{
if (!File.Exists(file))
return null;
using (var fs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.Read))
{
return Scan(scanner, fs, file);
}
}
/// <inheritdoc/>
public ConcurrentDictionary<string, ConcurrentQueue<string>> Scan(Scanner scanner, Stream stream, string file)
{
// If the BD+ file itself fails
try
{
// Create the wrapper
BinaryObjectScanner.Wrappers.BDPlusSVM svm = BinaryObjectScanner.Wrappers.BDPlusSVM.Create(stream);
if (svm == null)
return null;
// Setup the output
var protections = new ConcurrentDictionary<string, ConcurrentQueue<string>>();
protections[file] = new ConcurrentQueue<string>();
// Format the date
string date = $"{svm.Year:0000}/{svm.Month:00}/{svm.Day:00}";
// Add and return the protection
protections[file].Enqueue($"BD+ {date}");
return protections;
}
catch (Exception ex)
{
if (scanner.IncludeDebug) Console.WriteLine(ex);
}
return null;
}
}
}

View File

@@ -1,49 +0,0 @@
using System;
using System.Collections.Concurrent;
using System.IO;
using BurnOutSharp.Interfaces;
using static BinaryObjectScanner.Utilities.Dictionary;
namespace BurnOutSharp.FileType
{
/// <summary>
/// Link Data Security encrypted file
/// </summary>
public class LDSCRYPT : IScannable
{
/// <inheritdoc/>
public ConcurrentDictionary<string, ConcurrentQueue<string>> Scan(Scanner scanner, string file)
{
if (!File.Exists(file))
return null;
using (var fs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.Read))
{
return Scan(scanner, fs, file);
}
}
/// <inheritdoc/>
public ConcurrentDictionary<string, ConcurrentQueue<string>> Scan(Scanner scanner, Stream stream, string file)
{
var protections = new ConcurrentDictionary<string, ConcurrentQueue<string>>();
try
{
byte[] magic = new byte[16];
stream.Read(magic, 0, 16);
if (Tools.FileTypeTools.GetFileType(magic) == SupportedFileType.LDSCRYPT)
{
AppendToDictionary(protections, file, "Link Data Security encrypted file");
return protections;
}
}
catch (Exception ex)
{
if (scanner.IncludeDebug) Console.WriteLine(ex);
}
return null;
}
}
}

View File

@@ -1,49 +0,0 @@
using System;
using System.Collections.Concurrent;
using System.IO;
using BurnOutSharp.Interfaces;
using static BinaryObjectScanner.Utilities.Dictionary;
namespace BurnOutSharp.FileType
{
/// <summary>
/// PlayJ audio file
/// </summary>
public class PLJ : IScannable
{
/// <inheritdoc/>
public ConcurrentDictionary<string, ConcurrentQueue<string>> Scan(Scanner scanner, string file)
{
if (!File.Exists(file))
return null;
using (var fs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.Read))
{
return Scan(scanner, fs, file);
}
}
/// <inheritdoc/>
public ConcurrentDictionary<string, ConcurrentQueue<string>> Scan(Scanner scanner, Stream stream, string file)
{
var protections = new ConcurrentDictionary<string, ConcurrentQueue<string>>();
try
{
byte[] magic = new byte[16];
stream.Read(magic, 0, 16);
if (Tools.FileTypeTools.GetFileType(magic) == SupportedFileType.PLJ)
{
AppendToDictionary(protections, file, "PlayJ Audio File");
return protections;
}
}
catch (Exception ex)
{
if (scanner.IncludeDebug) Console.WriteLine(ex);
}
return null;
}
}
}

View File

@@ -344,6 +344,17 @@ namespace BurnOutSharp
#region Non-Archive File Types
// Create a detectable for the given file type
var detectable = CreateDetectable(fileType);
// If we're scanning file contents
if (detectable != null && ScanContents)
{
string subProtection = detectable.Detect(stream, fileName, IncludeDebug);
if (!string.IsNullOrWhiteSpace(subProtection))
AppendToDictionary(protections, fileName, subProtection);
}
// Create a scannable for the given file type
var scannable = CreateScannable(fileType);
@@ -417,6 +428,25 @@ namespace BurnOutSharp
#region Helpers
/// <summary>
/// Create an instance of a detectable based on file type
/// </summary>
private static IDetectable CreateDetectable(SupportedFileType fileType)
{
switch (fileType)
{
case SupportedFileType.AACSMediaKeyBlock: return new BinaryObjectScanner.FileType.AACSMediaKeyBlock();
case SupportedFileType.BDPlusSVM: return new BinaryObjectScanner.FileType.BDPlusSVM();
//case SupportedFileType.CIA: return new BinaryObjectScanner.FileType.CIA();
case SupportedFileType.LDSCRYPT: return new BinaryObjectScanner.FileType.LDSCRYPT();
//case SupportedFileType.N3DS: return new BinaryObjectScanner.FileType.N3DS();
//case SupportedFileType.Nitro: return new BinaryObjectScanner.FileType.Nitro();
case SupportedFileType.PLJ: return new BinaryObjectScanner.FileType.PLJ();
case SupportedFileType.SFFS: return new BinaryObjectScanner.FileType.SFFS();
default: return null;
}
}
/// <summary>
/// Create an instance of an extractable based on file type
/// </summary>
@@ -447,7 +477,7 @@ namespace BurnOutSharp
//case SupportedFileType.Quantum: return new BinaryObjectScanner.FileType.Quantum();
case SupportedFileType.RAR: return new BinaryObjectScanner.FileType.RAR();
case SupportedFileType.SevenZip: return new BinaryObjectScanner.FileType.SevenZip();
case SupportedFileType.SFFS: return new FileType.SFFS();
case SupportedFileType.SFFS: return new BinaryObjectScanner.FileType.SFFS();
case SupportedFileType.SGA: return new BinaryObjectScanner.FileType.SGA();
case SupportedFileType.TapeArchive: return new BinaryObjectScanner.FileType.TapeArchive();
case SupportedFileType.VBSP: return new BinaryObjectScanner.FileType.VBSP();
@@ -466,17 +496,7 @@ namespace BurnOutSharp
{
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 FileTypes.IniFile: return new FileType.IniFile();
case SupportedFileType.LDSCRYPT: return new FileType.LDSCRYPT();
//case SupportedFileType.N3DS: return new FileType.N3DS();
//case SupportedFileType.NCF: return new FileType.NCF();
//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();
default: return null;
}

View File

@@ -1,6 +1,5 @@
using System;
using System.IO;
using BinaryObjectScanner.FileType;
using BinaryObjectScanner.Matching;
using BinaryObjectScanner.Utilities;
using BinaryObjectScanner.Wrappers;
@@ -793,40 +792,40 @@ namespace BurnOutSharp.Tools
{
case SupportedFileType.AACSMediaKeyBlock: return AACSMediaKeyBlock.Create(data);
case SupportedFileType.BDPlusSVM: return BDPlusSVM.Create(data);
case SupportedFileType.BFPK: return BinaryObjectScanner.Wrappers.BFPK.Create(data);
case SupportedFileType.BSP: return BinaryObjectScanner.Wrappers.BSP.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 BinaryObjectScanner.Wrappers.CFB.Create(data);
case SupportedFileType.CFB: return CFB.Create(data);
case SupportedFileType.CIA: return CIA.Create(data);
case SupportedFileType.Executable: return DetermineExecutableType(data);
case SupportedFileType.GCF: return BinaryObjectScanner.Wrappers.GCF.Create(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.LDSCRYPT: return BinaryObjectScanner.Wrappers.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 BinaryObjectScanner.Wrappers.PAK.Create(data);
case SupportedFileType.PFF: return BinaryObjectScanner.Wrappers.PFF.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 BinaryObjectScanner.Wrappers.SGA.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 BinaryObjectScanner.Wrappers.VBSP.Create(data);
case SupportedFileType.VPK: return BinaryObjectScanner.Wrappers.VPK.Create(data);
case SupportedFileType.WAD: return BinaryObjectScanner.Wrappers.WAD.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 BinaryObjectScanner.Wrappers.XZP.Create(data);
case SupportedFileType.XZP: return XZP.Create(data);
default: return null;
}
}

View File

@@ -324,6 +324,7 @@ This section contains information on project and class organization principles t
| `BinaryObjectScanner.ASN1` | Flat directory structure. |
| `BinaryObjectScanner.Builders` | One file per executable type. |
| `BinaryObjectScanner.Compression` | One directory per compression type. |
| `BinaryObjectScanner.FileType` | One file per file type. |
| `BinaryObjectScanner.Interfaces` | One file per interface. |
| `BinaryObjectScanner.Matching` | Flat directory structure. Include interfaces and base classes. |
| `BinaryObjectScanner.Models` | One directory per executable type. One file per object model. |
@@ -343,11 +344,12 @@ This section contains information on in-code organization principles that depend
| Project | Description |
| --- | --- |
| `BurnOutSharp` | Varies from file to file. |
| `BurnOutSharp/FileType` | `IExtractable` implementations, `IScannable` implementations, helper methods. |
| `BurnOutSharp/FileType` | `IDetectable` implementations, `IExtractable` implementations, `IScannable` implementations, helper methods. |
| `BurnOutSharp/Tools` | Methods grouped by function. Regions ordered alphabetically. |
| `BinaryObjectScanner.ASN1` | Partial classes suggested for different implmentations. |
| `BinaryObjectScanner.Builders` | Two copies of each non-generic method: one for byte arrays and one for Streams. |
| `BinaryObjectScanner.Compression` | Varies from file to file. |
| `BinaryObjectScanner.FileType` | `IDetectable` implementations, `IExtractable` implementations, helper methods. |
| `BinaryObjectScanner.Interfaces` | Methods ordered alphabetically. |
| `BinaryObjectScanner.Matching` | Varies from file to file. |
| `BinaryObjectScanner.Models` | No methods at all, just properties. |

View File

@@ -12,6 +12,7 @@ This is a guide for any developers who wish to research protections, implement n
| `BinaryObjectScanner.ASN1` | Library containing classes and methods associated with Abstract Syntax Notation One and OID parsing. |
| `BinaryObjectScanner.Builder` | Library containing classes that assist in populating the various object models defined in `BinaryObjectScanner.Models`. Builders can work with either byte arrays or streams for input. At the time of writing, the following executable types have builders: **MS-DOS**, **New Executable**, **Portable Executable**. |
| `BinaryObjectScanner.Compression` | Library containing classes that deal with different compression formats. This library is used extensively by the wrappers in `BinaryObjectScanner.Wrappers`. |
| `BinaryObjectScanner.FileType` | Library containing file type definitions specific to scanning. |
| `BinaryObjectScanner.Interfaces` | Library containing interface definitions for scanning and detection. |
| `BinaryObjectScanner.Matching` | Library containing models and logic for generic searching and matching. This library is used extensively by the packer and protection checks in `BurnOutSharp`. |
| `BinaryObjectScanner.Models` | Library containing object models that represent various pieces of known executable formats. At the time of writing, the following executable types have models: **MS-DOS**, **New Executable**, **Linear Executable (partial)**, **Portable Executable**. |
@@ -88,7 +89,7 @@ Adding a new checker or format should happen in a few distinct steps:
1. Create a skeleton class representing the new checker or format
- If it is a new supported file type (such as an archive format), create the file in `BurnOutSharp/FileType/`. By default, you will need to implement `BurnOutSharp.Interfaces.IScannable` or `BinaryObjectScanner.Interfaces.IExtractable`. Do not implement any other interfaces. Please consider asking project maintainers before doing this work, especially if there are external dependencies.
- If it is a new supported file type (such as an archive format), create the file in `BinaryObjectScanner.FileType`. By default, you will need to implement `BurnOutSharp.Interfaces.IDetectable` or `BinaryObjectScanner.Interfaces.IExtractable`. Do not implement any other interfaces. Please consider asking project maintainers before doing this work, especially if there are external dependencies.
- If it is a new supported executable packer, compressor, or installer format, create the file in `BinaryObjectScanner.Packer`. By default, you will need to implement `BinaryObjectScanner.Interfaces.IExtractable` as well as at least one of: `BinaryObjectScanner.Interfaces.ILinearExecutableCheck`, `BinaryObjectScanner.Interfaces.INewExecutableCheck`, and `BinaryObjectScanner.Interfaces.IPortableExecutableCheck`. It is exceptionally rare to need to implement `BinaryObjectScanner.Interfaces.IPathCheck`.