Compare commits

...

20 Commits
3.2.1 ... 3.2.3

Author SHA1 Message Date
Matt Nadareski
eb03470625 Bump version 2024-11-21 11:20:19 -05:00
Matt Nadareski
b1aa2fc73a Enable MPQ on .NET Framework 4.0 2024-11-21 10:40:10 -05:00
Matt Nadareski
cd21c76c97 Add versions to executables 2024-11-21 10:35:15 -05:00
Matt Nadareski
9e205ddf2a More incidental cleanup 2024-11-21 01:32:30 -05:00
Matt Nadareski
07a183955b Reduce framework gating in SecuROM 2024-11-20 23:41:09 -05:00
Matt Nadareski
b49c6e96fd Add guards around previous commit 2024-11-20 21:48:37 -05:00
Matt Nadareski
148cfed141 Add executable extraction to tool 2024-11-20 21:45:15 -05:00
Matt Nadareski
cebbe6a1e8 Check overlay for embedded data as well 2024-11-20 21:33:56 -05:00
Matt Nadareski
558e23a9cd Clean up after last few commits 2024-11-20 21:18:12 -05:00
Matt Nadareski
d7c37f6e0a Lists lead to less Linq 2024-11-20 20:58:39 -05:00
Matt Nadareski
c05090db8c Update packages 2024-11-20 20:23:05 -05:00
Matt Nadareski
fa19304a6d Remove some framework gating 2024-11-20 20:10:18 -05:00
Matt Nadareski
ec4962a3c9 Use List where possible, Macrovision edition 2024-11-20 17:13:47 -05:00
Matt Nadareski
7122aa44a1 Use List where possible 2024-11-20 17:10:03 -05:00
Matt Nadareski
cf62be365c Use List where possible 2024-11-20 17:05:40 -05:00
Matt Nadareski
9cc2f99334 Quick package sync 2024-11-20 16:51:06 -05:00
Matt Nadareski
d9d9f23af9 Read entire file for content checks 2024-11-20 15:53:09 -05:00
Matt Nadareski
c29354f054 Add embedded archive scanning 2024-11-20 15:19:39 -05:00
Matt Nadareski
7738630952 Bump version 2024-11-16 00:00:00 -05:00
Matt Nadareski
c945ca4fe3 Make BOS compatible with RedumpLib 2024-11-15 23:59:23 -05:00
129 changed files with 1186 additions and 1365 deletions

View File

@@ -11,7 +11,7 @@
<Nullable>enable</Nullable>
<SuppressTfmSupportBuildWarnings>true</SuppressTfmSupportBuildWarnings>
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
<Version>3.2.1</Version>
<Version>3.2.3</Version>
<!-- Mostly added due to external libraries -->
<WarningsNotAsErrors>CS8600;CS8601;CS8602;CS8603;CS8604;CS8605;CS8618;CS8625;CS8634;CS8765;IL3000;NU5100</WarningsNotAsErrors>
@@ -44,14 +44,6 @@
</DefaultItemExcludes>
</PropertyGroup>
<!-- Exclude all StormLibSharp for .NET Framework 4.0 -->
<PropertyGroup Condition="$(TargetFramework.StartsWith(`net40`))">
<DefaultItemExcludes>
$(DefaultItemExcludes);
_EXTERNAL\stormlibsharp\src\**
</DefaultItemExcludes>
</PropertyGroup>
<!-- Exclude all external modules for .NET Framework 2.0, .NET Framework 3.5, or non-Windows
builds -->
<PropertyGroup Condition="$(TargetFramework.StartsWith(`net2`)) OR $(TargetFramework.StartsWith(`net3`)) OR !$(RuntimeIdentifier.StartsWith(`win-x86`))">
@@ -78,10 +70,14 @@
<!-- Support for old .NET versions -->
<ItemGroup Condition="$(TargetFramework.StartsWith(`net2`))">
<PackageReference Include="Net30.LinqBridge" Version="1.3.0" />
<PackageReference Include="Net35.Actions" Version="1.1.0" />
</ItemGroup>
<ItemGroup Condition="!$(TargetFramework.StartsWith(`net2`)) AND !$(TargetFramework.StartsWith(`net3`))">
<PackageReference Include="OpenMcdf" Version="2.3.1" />
</ItemGroup>
<ItemGroup Condition="$(TargetFramework.StartsWith(`net2`)) OR $(TargetFramework.StartsWith(`net3`)) OR $(TargetFramework.StartsWith(`net40`))">
<PackageReference Include="MinAsyncBridge" Version="0.12.4" />
</ItemGroup>
<ItemGroup Condition="!$(TargetFramework.StartsWith(`net2`)) AND !$(TargetFramework.StartsWith(`net3`)) AND !$(TargetFramework.StartsWith(`net40`)) AND !$(TargetFramework.StartsWith(`net452`))">
<PackageReference Include="SharpCompress" Version="0.38.0" />
<PackageReference Include="System.Text.Encoding.CodePages" Version="8.0.0" />
@@ -92,8 +88,8 @@
<PackageReference Include="SabreTools.Hashing" Version="1.4.0" />
<PackageReference Include="SabreTools.IO" Version="1.5.1" />
<PackageReference Include="SabreTools.Matching" Version="1.4.1" />
<PackageReference Include="SabreTools.Models" Version="1.5.1" />
<PackageReference Include="SabreTools.Serialization" Version="1.7.5" />
<PackageReference Include="SabreTools.Models" Version="1.5.3" />
<PackageReference Include="SabreTools.Serialization" Version="1.7.6" />
<PackageReference Include="UnshieldSharp" Version="1.9.1" />
<PackageReference Include="WiseUnpacker" Version="1.5.1" />
</ItemGroup>

View File

@@ -0,0 +1,9 @@
#if NET20
namespace System.Runtime.CompilerServices
{
[AttributeUsage(AttributeTargets.Assembly | AttributeTargets.Class | AttributeTargets.Method)]
internal sealed class ExtensionAttribute : Attribute {}
}
#endif

View File

@@ -62,7 +62,7 @@ namespace BinaryObjectScanner
WrapperType.TapeArchive => new FileType.TapeArchive(),
WrapperType.VBSP => new FileType.VBSP(),
WrapperType.VPK => new FileType.VPK(),
WrapperType.WAD => new FileType.WAD(),
WrapperType.WAD => new FileType.WAD3(),
WrapperType.XZ => new FileType.XZ(),
WrapperType.XZP => new FileType.XZP(),
_ => null,

View File

@@ -1,7 +1,7 @@
using System;
using System.Collections.Generic;
using System.IO;
using BinaryObjectScanner.Interfaces;
using SabreTools.Models.BSP;
namespace BinaryObjectScanner.FileType
{
@@ -30,10 +30,11 @@ namespace BinaryObjectScanner.FileType
if (bsp == null)
return false;
// TODO: Introduce helper methods for all specialty lump types
// Loop through and extract all files
Directory.CreateDirectory(outDir);
ExtractAllLumps(bsp, outDir);
ExtractAllTextures(bsp, outDir);
return true;
}
@@ -52,12 +53,12 @@ namespace BinaryObjectScanner.FileType
public static bool ExtractAllLumps(SabreTools.Serialization.Wrappers.BSP item, string outputDirectory)
{
// If we have no lumps
if (item.Model.Lumps == null || item.Model.Lumps.Length == 0)
if (item.Model.Header?.Lumps == null || item.Model.Header.Lumps.Length == 0)
return false;
// Loop through and extract all lumps to the output
bool allExtracted = true;
for (int i = 0; i < item.Model.Lumps.Length; i++)
for (int i = 0; i < item.Model.Header.Lumps.Length; i++)
{
allExtracted &= ExtractLump(item, i, outputDirectory);
}
@@ -74,15 +75,15 @@ namespace BinaryObjectScanner.FileType
public static bool ExtractLump(SabreTools.Serialization.Wrappers.BSP item, int index, string outputDirectory)
{
// If we have no lumps
if (item.Model.Lumps == null || item.Model.Lumps.Length == 0)
if (item.Model.Header?.Lumps == null || item.Model.Header.Lumps.Length == 0)
return false;
// If the lumps index is invalid
if (index < 0 || index >= item.Model.Lumps.Length)
if (index < 0 || index >= item.Model.Header.Lumps.Length)
return false;
// Get the lump
var lump = item.Model.Lumps[index];
var lump = item.Model.Header.Lumps[index];
if (lump == null)
return false;
@@ -93,12 +94,12 @@ namespace BinaryObjectScanner.FileType
// Create the filename
string filename = $"lump_{index}.bin";
switch (index)
switch ((LumpType)index)
{
case SabreTools.Models.BSP.Constants.HL_BSP_LUMP_ENTITIES:
case LumpType.LUMP_ENTITIES:
filename = "entities.ent";
break;
case SabreTools.Models.BSP.Constants.HL_BSP_LUMP_TEXTUREDATA:
case LumpType.LUMP_TEXTURES:
filename = "texture_data.bin";
break;
}
@@ -119,10 +120,8 @@ namespace BinaryObjectScanner.FileType
try
{
// Open the output file for writing
using (Stream fs = File.OpenWrite(filename))
{
fs.Write(data, 0, data.Length);
}
using Stream fs = File.OpenWrite(filename);
fs.Write(data, 0, data.Length);
}
catch
{
@@ -131,172 +130,5 @@ namespace BinaryObjectScanner.FileType
return true;
}
/// <summary>
/// Extract all textures from the BSP to an output directory
/// </summary>
/// <param name="outputDirectory">Output directory to write to</param>
/// <returns>True if all textures extracted, false otherwise</returns>
public static bool ExtractAllTextures(SabreTools.Serialization.Wrappers.BSP item, string outputDirectory)
{
// If we have no textures
if (item.Model.TextureHeader?.Offsets == null || item.Model.TextureHeader.Offsets.Length == 0)
return false;
// Loop through and extract all lumps to the output
bool allExtracted = true;
for (int i = 0; i < item.Model.TextureHeader.Offsets.Length; i++)
{
allExtracted &= ExtractTexture(item, i, outputDirectory);
}
return allExtracted;
}
/// <summary>
/// Extract a texture from the BSP to an output directory by index
/// </summary>
/// <param name="index">Lump index to extract</param>
/// <param name="outputDirectory">Output directory to write to</param>
/// <returns>True if the texture extracted, false otherwise</returns>
public static bool ExtractTexture(SabreTools.Serialization.Wrappers.BSP item, int index, string outputDirectory)
{
// If we have no textures
if (item.Model.Textures == null || item.Model.Textures.Length == 0)
return false;
// If the texture index is invalid
if (index < 0 || index >= item.Model.Textures.Length)
return false;
// Get the texture
var texture = item.Model.Textures[index];
if (texture == null)
return false;
// Read the data
var data = CreateTextureData(texture);
if (data == null)
return false;
// Create the filename
string filename = $"{texture.Name}.bmp";
// If we have an invalid output directory
if (string.IsNullOrEmpty(outputDirectory))
return false;
// Create the full output path
filename = Path.Combine(outputDirectory, filename);
// Ensure the output directory is created
var directoryName = Path.GetDirectoryName(filename);
if (directoryName != null)
Directory.CreateDirectory(directoryName);
// Try to write the data
try
{
// Open the output file for writing
using (Stream fs = File.OpenWrite(filename))
{
fs.Write(data, 0, data.Length);
}
}
catch
{
return false;
}
return true;
}
/// <summary>
/// Create a bitmap from the texture and palette data
/// </summary>
/// <param name="texture">Texture object to format</param>
/// <returns>Byte array representing the texture as a bitmap</returns>
private static byte[]? CreateTextureData(SabreTools.Models.BSP.Texture texture)
{
// If there's no palette data
if (texture.PaletteData == null || texture.PaletteData.Length == 0)
return null;
// If there's no texture data
if (texture.TextureData == null || texture.TextureData.Length == 0)
return null;
// Create the bitmap file header
var fileHeader = new SabreTools.Models.BMP.BITMAPFILEHEADER()
{
Type = ('M' << 8) | 'B',
Size = 14 + 40 + (texture.PaletteSize * 4) + (texture.Width * texture.Height),
OffBits = 14 + 40 + (texture.PaletteSize * 4),
};
// Create the bitmap info header
var infoHeader = new SabreTools.Models.BMP.BITMAPINFOHEADER
{
Size = 40,
Width = (int)texture.Width,
Height = (int)texture.Height,
Planes = 1,
BitCount = 8,
SizeImage = 0,
ClrUsed = texture.PaletteSize,
ClrImportant = texture.PaletteSize,
};
// Reformat the palette data
byte[] paletteData = new byte[texture.PaletteSize * 4];
for (uint i = 0; i < texture.PaletteSize; i++)
{
paletteData[i * 4 + 0] = texture.PaletteData[i * 3 + 2];
paletteData[i * 4 + 1] = texture.PaletteData[i * 3 + 1];
paletteData[i * 4 + 2] = texture.PaletteData[i * 3 + 0];
paletteData[i * 4 + 3] = 0;
}
// Reformat the pixel data
byte[] pixelData = new byte[texture.Width * texture.Height];
for (uint i = 0; i < texture.Width; i++)
{
for (uint j = 0; j < texture.Height; j++)
{
pixelData[i + ((texture.Height - 1 - j) * texture.Width)] = texture.TextureData[i + j * texture.Width];
}
}
// Build the file data
List<byte> buffer = new List<byte>();
// Bitmap file header
buffer.AddRange(BitConverter.GetBytes(fileHeader.Type));
buffer.AddRange(BitConverter.GetBytes(fileHeader.Size));
buffer.AddRange(BitConverter.GetBytes(fileHeader.Reserved1));
buffer.AddRange(BitConverter.GetBytes(fileHeader.Reserved2));
buffer.AddRange(BitConverter.GetBytes(fileHeader.OffBits));
// Bitmap info header
buffer.AddRange(BitConverter.GetBytes(infoHeader.Size));
buffer.AddRange(BitConverter.GetBytes(infoHeader.Width));
buffer.AddRange(BitConverter.GetBytes(infoHeader.Height));
buffer.AddRange(BitConverter.GetBytes(infoHeader.Planes));
buffer.AddRange(BitConverter.GetBytes(infoHeader.BitCount));
buffer.AddRange(BitConverter.GetBytes(infoHeader.Compression));
buffer.AddRange(BitConverter.GetBytes(infoHeader.SizeImage));
buffer.AddRange(BitConverter.GetBytes(infoHeader.XPelsPerMeter));
buffer.AddRange(BitConverter.GetBytes(infoHeader.YPelsPerMeter));
buffer.AddRange(BitConverter.GetBytes(infoHeader.ClrUsed));
buffer.AddRange(BitConverter.GetBytes(infoHeader.ClrImportant));
// Palette data
buffer.AddRange(paletteData);
// Pixel data
buffer.AddRange(pixelData);
return buffer.ToArray();
}
}
}

View File

@@ -94,41 +94,49 @@ namespace BinaryObjectScanner.FileType
if (wrapper is MSDOS mz)
{
// Standard checks
var subProtections = RunExecutableChecks(file, mz, StaticChecks.MSDOSExecutableCheckClasses, includeDebug);
var subProtections
= RunExecutableChecks(file, mz, StaticChecks.MSDOSExecutableCheckClasses, includeDebug);
protections.Append(file, subProtections.Values);
// Extractable checks
var extractedProtections = HandleExtractableProtections(file, mz, subProtections.Keys, getProtections, includeDebug);
var extractedProtections
= HandleExtractableProtections(file, mz, subProtections.Keys, getProtections, includeDebug);
protections.Append(extractedProtections);
}
else if (wrapper is LinearExecutable lex)
{
// Standard checks
var subProtections = RunExecutableChecks(file, lex, StaticChecks.LinearExecutableCheckClasses, includeDebug);
var subProtections
= RunExecutableChecks(file, lex, StaticChecks.LinearExecutableCheckClasses, includeDebug);
protections.Append(file, subProtections.Values);
// Extractable checks
var extractedProtections = HandleExtractableProtections(file, lex, subProtections.Keys, getProtections, includeDebug);
var extractedProtections
= HandleExtractableProtections(file, lex, subProtections.Keys, getProtections, includeDebug);
protections.Append(extractedProtections);
}
else if (wrapper is NewExecutable nex)
{
// Standard checks
var subProtections = RunExecutableChecks(file, nex, StaticChecks.NewExecutableCheckClasses, includeDebug);
var subProtections
= RunExecutableChecks(file, nex, StaticChecks.NewExecutableCheckClasses, includeDebug);
protections.Append(file, subProtections.Values);
// Extractable checks
var extractedProtections = HandleExtractableProtections(file, nex, subProtections.Keys, getProtections, includeDebug);
var extractedProtections
= HandleExtractableProtections(file, nex, subProtections.Keys, getProtections, includeDebug);
protections.Append(extractedProtections);
}
else if (wrapper is PortableExecutable pex)
{
// Standard checks
var subProtections = RunExecutableChecks(file, pex, StaticChecks.PortableExecutableCheckClasses, includeDebug);
var subProtections
= RunExecutableChecks(file, pex, StaticChecks.PortableExecutableCheckClasses, includeDebug);
protections.Append(file, subProtections.Values);
// Extractable checks
var extractedProtections = HandleExtractableProtections(file, pex, subProtections.Keys, getProtections, includeDebug);
var extractedProtections
= HandleExtractableProtections(file, pex, subProtections.Keys, getProtections, includeDebug);
protections.Append(extractedProtections);
}
@@ -155,10 +163,15 @@ namespace BinaryObjectScanner.FileType
else if (!File.Exists(file))
return protections;
// If the stream isn't seekable
if (!stream.CanSeek)
return protections;
// Read the file contents
byte[] fileContent = [];
try
{
stream.Seek(0, SeekOrigin.Begin);
fileContent = stream.ReadBytes((int)stream.Length);
if (fileContent == null)
return protections;
@@ -240,7 +253,7 @@ namespace BinaryObjectScanner.FileType
/// <returns>Set of protections found from extraction, empty on error</returns>
private static ProtectionDictionary HandleExtractableProtections<T, U>(string file,
T exe,
IEnumerable<U> checks,
ICollection<U> checks,
Func<string, ProtectionDictionary>? getProtections,
bool includeDebug)
where T : WrapperBase

View File

@@ -126,19 +126,18 @@ namespace BinaryObjectScanner.FileType
try
{
// Open the output file for writing
using (Stream fs = File.OpenWrite(filename))
{
// Now read the data sequentially and write out while we have data left
long fileSize = file.Size;
for (int i = 0; i < dataBlockOffsets.Count; i++)
{
int readSize = (int)Math.Min(item.Model.DataBlockHeader?.BlockSize ?? 0, fileSize);
var data = item.ReadFromDataSource((int)dataBlockOffsets[i], readSize);
if (data == null)
return false;
using Stream fs = File.OpenWrite(filename);
fs.Write(data, 0, data.Length);
}
// Now read the data sequentially and write out while we have data left
long fileSize = file.Size;
for (int i = 0; i < dataBlockOffsets.Count; i++)
{
int readSize = (int)Math.Min(item.Model.DataBlockHeader?.BlockSize ?? 0, fileSize);
var data = item.ReadFromDataSource((int)dataBlockOffsets[i], readSize);
if (data == null)
return false;
fs.Write(data, 0, data.Length);
}
}
catch

View File

@@ -28,12 +28,8 @@ namespace BinaryObjectScanner.FileType
byte[] magic = new byte[16];
int read = stream.Read(magic, 0, 16);
#if NET20
if (Extensions.StartsWith(magic, new byte?[] { 0x4C, 0x44, 0x53, 0x43, 0x52, 0x59, 0x50, 0x54 }))
#else
if (magic.StartsWith(new byte?[] { 0x4C, 0x44, 0x53, 0x43, 0x52, 0x59, 0x50, 0x54 }))
#endif
return "Link Data Security encrypted file";
return "Link Data Security encrypted file";
}
catch (Exception ex)
{

View File

@@ -25,7 +25,7 @@ namespace BinaryObjectScanner.FileType
/// <inheritdoc/>
public bool Extract(Stream? stream, string file, string outDir, bool includeDebug)
{
#if NET20 || NET35 || NET40 || !WIN
#if NET20 || NET35 || !WIN
// Not supported for old .NET due to feature requirements
// Not supported in non-Windows builds due to DLL requirements
return false;

View File

@@ -108,10 +108,8 @@ namespace BinaryObjectScanner.FileType
try
{
// Open the output file for writing
using (Stream fs = File.OpenWrite(filename))
{
fs.Write(data, 0, data.Length);
}
using Stream fs = File.OpenWrite(filename);
fs.Write(data, 0, data.Length);
}
catch
{

View File

@@ -28,11 +28,7 @@ namespace BinaryObjectScanner.FileType
byte[] magic = new byte[16];
int read = stream.Read(magic, 0, 16);
#if NET20
if (Extensions.StartsWith(magic, new byte?[] { 0xFF, 0x9D, 0x53, 0x4B }))
#else
if (magic.StartsWith(new byte?[] { 0xFF, 0x9D, 0x53, 0x4B }))
#endif
return "PlayJ Audio File";
}
catch (Exception ex)

View File

@@ -32,11 +32,7 @@ namespace BinaryObjectScanner.FileType
// RASGI2.0
// Found in the ".rgs" files in IA item "Nova_RealArcadeCD_USA".
#if NET20
if (Extensions.StartsWith(magic, new byte?[] { 0x52, 0x41, 0x53, 0x47, 0x49, 0x32, 0x2E, 0x30 }))
#else
if (magic.StartsWith(new byte?[] { 0x52, 0x41, 0x53, 0x47, 0x49, 0x32, 0x2E, 0x30 }))
#endif
return "RealArcade Installer";
}
catch (Exception ex)

View File

@@ -32,11 +32,7 @@ namespace BinaryObjectScanner.FileType
// XZip2.0
// Found in the ".mez" files in IA item "Nova_RealArcadeCD_USA".
#if NET20
if (Extensions.StartsWith(magic, new byte?[] { 0x58, 0x5A, 0x69, 0x70, 0x32, 0x2E, 0x30 }))
#else
if (magic.StartsWith(new byte?[] { 0x58, 0x5A, 0x69, 0x70, 0x32, 0x2E, 0x30 }))
#endif
return "RealArcade Mezzanine";
}
catch (Exception ex)

View File

@@ -29,12 +29,8 @@ namespace BinaryObjectScanner.FileType
byte[] magic = new byte[16];
int read = stream.Read(magic, 0, 16);
#if NET20
if (Extensions.StartsWith(magic, new byte?[] { 0x53, 0x46, 0x46, 0x53 }))
#else
if (magic.StartsWith(new byte?[] { 0x53, 0x46, 0x46, 0x53 }))
#endif
return "StarForce Filesystem Container";
return "StarForce Filesystem Container";
}
catch (Exception ex)
{

View File

@@ -1,6 +1,7 @@
using System;
using System.IO;
using BinaryObjectScanner.Interfaces;
using SabreTools.Models.BSP;
namespace BinaryObjectScanner.FileType
{
@@ -29,6 +30,8 @@ namespace BinaryObjectScanner.FileType
if (vbsp == null)
return false;
// TODO: Introduce helper methods for all specialty lump types
// Loop through and extract all files
Directory.CreateDirectory(outDir);
ExtractAllLumps(vbsp, outDir);
@@ -91,12 +94,12 @@ namespace BinaryObjectScanner.FileType
// Create the filename
string filename = $"lump_{index}.bin";
switch (index)
switch ((LumpType)index)
{
case SabreTools.Models.VBSP.Constants.HL_VBSP_LUMP_ENTITIES:
case LumpType.LUMP_ENTITIES:
filename = "entities.ent";
break;
case SabreTools.Models.VBSP.Constants.HL_VBSP_LUMP_PAKFILE:
case LumpType.LUMP_PAKFILE:
filename = "pakfile.zip";
break;
}
@@ -117,10 +120,8 @@ namespace BinaryObjectScanner.FileType
try
{
// Open the output file for writing
using (Stream fs = File.OpenWrite(filename))
{
fs.Write(data, 0, data.Length);
}
using Stream fs = File.OpenWrite(filename);
fs.Write(data, 0, data.Length);
}
catch
{

View File

@@ -165,10 +165,8 @@ namespace BinaryObjectScanner.FileType
try
{
// Open the output file for writing
using (Stream fs = File.OpenWrite(filename))
{
fs.Write(data, 0, data.Length);
}
using Stream fs = File.OpenWrite(filename);
fs.Write(data, 0, data.Length);
}
catch
{

View File

@@ -7,7 +7,7 @@ namespace BinaryObjectScanner.FileType
/// <summary>
/// Half-Life Texture Package File
/// </summary>
public class WAD : IExtractable
public class WAD3 : IExtractable
{
/// <inheritdoc/>
public bool Extract(string file, string outDir, bool includeDebug)
@@ -25,7 +25,7 @@ namespace BinaryObjectScanner.FileType
try
{
// Create the wrapper
var wad = SabreTools.Serialization.Wrappers.WAD.Create(stream);
var wad = SabreTools.Serialization.Wrappers.WAD3.Create(stream);
if (wad == null)
return false;
@@ -43,19 +43,19 @@ namespace BinaryObjectScanner.FileType
}
/// <summary>
/// Extract all lumps from the WAD to an output directory
/// Extract all lumps from the WAD3 to an output directory
/// </summary>
/// <param name="outputDirectory">Output directory to write to</param>
/// <returns>True if all lumps extracted, false otherwise</returns>
public static bool ExtractAllLumps(SabreTools.Serialization.Wrappers.WAD item, string outputDirectory)
public static bool ExtractAllLumps(SabreTools.Serialization.Wrappers.WAD3 item, string outputDirectory)
{
// If we have no lumps
if (item.Model.Lumps == null || item.Model.Lumps.Length == 0)
if (item.Model.DirEntries == null || item.Model.DirEntries.Length == 0)
return false;
// Loop through and extract all lumps to the output
bool allExtracted = true;
for (int i = 0; i < item.Model.Lumps.Length; i++)
for (int i = 0; i < item.Model.DirEntries.Length; i++)
{
allExtracted &= ExtractLump(item, i, outputDirectory);
}
@@ -64,23 +64,23 @@ namespace BinaryObjectScanner.FileType
}
/// <summary>
/// Extract a lump from the WAD to an output directory by index
/// Extract a lump from the WAD3 to an output directory by index
/// </summary>
/// <param name="index">Lump index to extract</param>
/// <param name="outputDirectory">Output directory to write to</param>
/// <returns>True if the lump extracted, false otherwise</returns>
public static bool ExtractLump(SabreTools.Serialization.Wrappers.WAD item, int index, string outputDirectory)
public static bool ExtractLump(SabreTools.Serialization.Wrappers.WAD3 item, int index, string outputDirectory)
{
// If we have no lumps
if (item.Model.Lumps == null || item.Model.Lumps.Length == 0)
if (item.Model.DirEntries == null || item.Model.DirEntries.Length == 0)
return false;
// If the lumps index is invalid
if (index < 0 || index >= item.Model.Lumps.Length)
if (index < 0 || index >= item.Model.DirEntries.Length)
return false;
// Get the lump
var lump = item.Model.Lumps[index];
var lump = item.Model.DirEntries[index];
if (lump == null)
return false;
@@ -108,10 +108,8 @@ namespace BinaryObjectScanner.FileType
try
{
// Open the output file for writing
using (Stream fs = File.OpenWrite(filename))
{
fs.Write(data, 0, data.Length);
}
using Stream fs = File.OpenWrite(filename);
fs.Write(data, 0, data.Length);
}
catch
{

View File

@@ -117,10 +117,8 @@ namespace BinaryObjectScanner.FileType
try
{
// Open the output file for writing
using (Stream fs = File.OpenWrite(filename))
{
fs.Write(data, 0, data.Length);
}
using Stream fs = File.OpenWrite(filename);
fs.Write(data, 0, data.Length);
}
catch
{

View File

@@ -14,9 +14,9 @@ namespace BinaryObjectScanner.Interfaces
/// Check a file path for protections based on path name
/// </summary>
/// <param name="path">Path to check for protection indicators</param>
/// <param name="files">Enumerable of strings representing files in a directory</param>
/// <param name="files">List of strings representing files in a directory</param>
/// <remarks>This can do some limited content checking as well, but it's suggested to use a content check instead, if possible</remarks>
IEnumerable<string> CheckDirectoryPath(string path, IEnumerable<string>? files);
List<string> CheckDirectoryPath(string path, List<string>? files);
/// <summary>
/// Check a file path for protections based on path name

View File

@@ -19,8 +19,7 @@ namespace BinaryObjectScanner.Packer
return null;
// Get the .aspack section, if it exists
bool aspackSection = pex.ContainsSection(".aspack", exact: true);
if (aspackSection)
if (pex.ContainsSection(".aspack", exact: true))
return "ASPack 2.29";
// TODO: Re-enable all Entry Point checks after implementing
@@ -60,10 +59,10 @@ namespace BinaryObjectScanner.Packer
/// Generate the set of matchers used for each section
/// </summary>
/// <returns></returns>
private List<ContentMatchSet> GenerateMatchers()
private static List<ContentMatchSet> GenerateMatchers()
{
return new List<ContentMatchSet>
{
return
[
#region No Wildcards (Long)
new(new byte?[]
@@ -641,7 +640,7 @@ namespace BinaryObjectScanner.Packer
new(new byte?[] { 0x60, 0xE8, 0x00, 0x00, 0x00, 0x00, 0x5D, 0x81, 0xED }, "ASPack 1.02b/1.08.03"),
#endregion
};
];
}
}
}

View File

@@ -27,7 +27,7 @@ namespace BinaryObjectScanner.Packer
name = Utilities.GetLegalCopyright(pex);
if (name?.StartsWith("Runtime Engine", StringComparison.OrdinalIgnoreCase) == true)
return $"AutoPlay Media Studio {GetVersion(pex)}";
*/
*/
return null;
}
@@ -38,7 +38,7 @@ namespace BinaryObjectScanner.Packer
return false;
}
private string GetVersion(PortableExecutable pex)
private static string GetVersion(PortableExecutable pex)
{
// Check the product version explicitly
var version = pex.ProductVersion;

View File

@@ -1,7 +1,6 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using BinaryObjectScanner.Interfaces;
using SabreTools.Compression.zlib;
using SabreTools.Matching;
@@ -24,23 +23,23 @@ namespace BinaryObjectScanner.Packer
return null;
// If there are exactly 2 resources with type 99
if (pex.FindResourceByNamedType("99, ").Count() == 2)
if (pex.FindResourceByNamedType("99, ").Count == 2)
return "CExe";
if (pex.StubExecutableData != null)
{
var matchers = new List<ContentMatchSet>
{
new(new byte?[]
{
0x25, 0x57, 0x6F, 0xC1, 0x61, 0x36, 0x01, 0x92,
0x61, 0x36, 0x01, 0x92, 0x61, 0x36, 0x01, 0x92,
0x61, 0x36, 0x00, 0x92, 0x7B, 0x36, 0x01, 0x92,
0x03, 0x29, 0x12, 0x92, 0x66, 0x36, 0x01, 0x92,
0x89, 0x29, 0x0A, 0x92, 0x60, 0x36, 0x01, 0x92,
0xD9, 0x30, 0x07, 0x92, 0x60, 0x36, 0x01, 0x92
}, "CExe")
};
new(new byte?[]
{
0x25, 0x57, 0x6F, 0xC1, 0x61, 0x36, 0x01, 0x92,
0x61, 0x36, 0x01, 0x92, 0x61, 0x36, 0x01, 0x92,
0x61, 0x36, 0x00, 0x92, 0x7B, 0x36, 0x01, 0x92,
0x03, 0x29, 0x12, 0x92, 0x66, 0x36, 0x01, 0x92,
0x89, 0x29, 0x0A, 0x92, 0x60, 0x36, 0x01, 0x92,
0xD9, 0x30, 0x07, 0x92, 0x60, 0x36, 0x01, 0x92
}, "CExe")
};
var match = MatchUtil.GetFirstMatch(file, pex.StubExecutableData, matchers, includeDebug);
if (!string.IsNullOrEmpty(match))
@@ -55,19 +54,21 @@ namespace BinaryObjectScanner.Packer
{
try
{
// Get all resources of type 99 with index 2
var resources = pex.FindResourceByNamedType("99, 2");
if (resources == null || resources.Count == 0)
return false;
// Get the first resource of type 99 with index 2
var payload = pex.FindResourceByNamedType("99, 2").FirstOrDefault();
var payload = resources[0];
if (payload == null || payload.Length == 0)
return false;
// Determine which compression was used
bool zlib = pex.FindResourceByNamedType("99, 1").Any();
// Create the output data buffer
var data = new byte[0];
byte[]? data = [];
// If we had the decompression DLL included, it's zlib
if (zlib)
if (pex.FindResourceByNamedType("99, 1").Count > 0)
{
try
{

View File

@@ -28,71 +28,67 @@ namespace BinaryObjectScanner.Packer
return null;
// Get the .text section, if it exists
if (pex.ContainsSection(".text"))
var textData = pex.GetFirstSectionData(".text");
if (textData != null)
{
var textData = pex.GetFirstSectionData(".text");
if (textData != null)
var matchers = new List<ContentMatchSet>
{
var matchers = new List<ContentMatchSet>
// Adapted from https://github.com/cod3nym/detection-rules/blob/main/yara/dotnet/obf_net_reactor.yar and confirmed to work with "KalypsoLauncher.dll" from Redump entry 95617.
// <PrivateImplementationDetails>{[8]-[4]-[4]-[4]-[12]}
new(new byte?[]
{
// Adapted from https://github.com/cod3nym/detection-rules/blob/main/yara/dotnet/obf_net_reactor.yar and confirmed to work with "KalypsoLauncher.dll" from Redump entry 95617.
// <PrivateImplementationDetails>{[8]-[4]-[4]-[4]-[12]}
new(new byte?[]
{
0x3C, 0x50, 0x72, 0x69, 0x76, 0x61, 0x74, 0x65,
0x49, 0x6D, 0x70, 0x6C, 0x65, 0x6D, 0x65, 0x6E,
0x74, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x44, 0x65,
0x74, 0x61, 0x69, 0x6C, 0x73, 0x3E, 0x7B, null,
null, null, null, null, null, null, null, 0x2D,
null, null, null, null, 0x2D, null, null, null,
null, 0x2D, null, null, null, null, 0x2D, null,
null, null, null, null, null, null, null, null,
null, null, null, 0x7D
}, ".NET Reactor"),
0x3C, 0x50, 0x72, 0x69, 0x76, 0x61, 0x74, 0x65,
0x49, 0x6D, 0x70, 0x6C, 0x65, 0x6D, 0x65, 0x6E,
0x74, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x44, 0x65,
0x74, 0x61, 0x69, 0x6C, 0x73, 0x3E, 0x7B, null,
null, null, null, null, null, null, null, 0x2D,
null, null, null, null, 0x2D, null, null, null,
null, 0x2D, null, null, null, null, 0x2D, null,
null, null, null, null, null, null, null, null,
null, null, null, 0x7D
}, ".NET Reactor"),
// Modified from the previous detection to detect a presumably newer version of .NET Reactor found in "KalypsoLauncher.dll" version 2.0.4.2.
// TODO: Check if this can/should be made more specific.
// <PrivateImplementationDetails>.RSA
new(new byte?[]
{
0x3C, 0x50, 0x72, 0x69, 0x76, 0x61, 0x74, 0x65,
0x49, 0x6D, 0x70, 0x6C, 0x65, 0x6D, 0x65, 0x6E,
0x74, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x44, 0x65,
0x74, 0x61, 0x69, 0x6C, 0x73, 0x3E, 0x00, 0x52,
0x53, 0x41
}, ".NET Reactor"),
// Modified from the previous detection to detect a presumably newer version of .NET Reactor found in "KalypsoLauncher.dll" version 2.0.4.2.
// TODO: Check if this can/should be made more specific.
// <PrivateImplementationDetails>.RSA
new(new byte?[]
{
0x3C, 0x50, 0x72, 0x69, 0x76, 0x61, 0x74, 0x65,
0x49, 0x6D, 0x70, 0x6C, 0x65, 0x6D, 0x65, 0x6E,
0x74, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x44, 0x65,
0x74, 0x61, 0x69, 0x6C, 0x73, 0x3E, 0x00, 0x52,
0x53, 0x41
}, ".NET Reactor"),
// Adapted from https://github.com/cod3nym/detection-rules/blob/main/yara/dotnet/obf_net_reactor.yar and confirmed to work with "KalypsoLauncher.dll" from Redump entry 95617.
// 3{.[9].-.[9].-.[9].}
new(new byte?[]
{
0x33, 0x7B, 0x00, null, null, null, null, null,
null, null, null, null, 0x00, 0x2D, 0x00, null,
null, null, null, null, null, null, null, null,
0x00, 0x2D, 0x00, null, null, null, null, null,
null, null, null, null, 0x00, 0x2D, 0x00, null,
null, null, null, null, null, null, null, null,
0x00, 0x7D, 0x00
}, ".NET Reactor (Unconfirmed - Please report to us on GitHub)"),
// Adapted from https://github.com/cod3nym/detection-rules/blob/main/yara/dotnet/obf_net_reactor.yar and confirmed to work with "KalypsoLauncher.dll" from Redump entry 95617.
// <Module>{[8]-[4]-[4]-[4]-[12]}
new(new byte?[]
{
0x3C, 0x4D, 0x6F, 0x64, 0x75, 0x6C, 0x65, 0x3E,
0x7B, null, null, null, null, null, null, null,
null, 0x2D, null, null, null, null, 0x2D, null,
null, null, null, 0x2D, null, null, null, null,
0x2D, null, null, null, null, null, null, null,
null, null, null, null, null, 0x7D
}, ".NET Reactor (Unconfirmed - Please report to us on GitHub)")
};
// Adapted from https://github.com/cod3nym/detection-rules/blob/main/yara/dotnet/obf_net_reactor.yar and confirmed to work with "KalypsoLauncher.dll" from Redump entry 95617.
// 3{.[9].-.[9].-.[9].}
new(new byte?[]
{
0x33, 0x7B, 0x00, null, null, null, null, null,
null, null, null, null, 0x00, 0x2D, 0x00, null,
null, null, null, null, null, null, null, null,
0x00, 0x2D, 0x00, null, null, null, null, null,
null, null, null, null, 0x00, 0x2D, 0x00, null,
null, null, null, null, null, null, null, null,
0x00, 0x7D, 0x00
}, ".NET Reactor (Unconfirmed - Please report to us on GitHub)"),
// Adapted from https://github.com/cod3nym/detection-rules/blob/main/yara/dotnet/obf_net_reactor.yar and confirmed to work with "KalypsoLauncher.dll" from Redump entry 95617.
// <Module>{[8]-[4]-[4]-[4]-[12]}
new(new byte?[]
{
0x3C, 0x4D, 0x6F, 0x64, 0x75, 0x6C, 0x65, 0x3E,
0x7B, null, null, null, null, null, null, null,
null, 0x2D, null, null, null, null, 0x2D, null,
null, null, null, 0x2D, null, null, null, null,
0x2D, null, null, null, null, null, null, null,
null, null, null, null, null, 0x7D
}, ".NET Reactor (Unconfirmed - Please report to us on GitHub)")
};
return MatchUtil.GetFirstMatch(file, textData, matchers, includeDebug);
}
return MatchUtil.GetFirstMatch(file, textData, matchers, includeDebug);
}
return null;
}

View File

@@ -15,26 +15,25 @@ namespace BinaryObjectScanner.Packer
/// <inheritdoc/>
public string? CheckContents(string file, byte[] fileContent, bool includeDebug)
{
// Only allow during debug
if (!includeDebug)
return null;
// TODO: Obtain a sample to find where this string is in a typical executable
if (includeDebug)
var contentMatchSets = new List<ContentMatchSet>
{
var contentMatchSets = new List<ContentMatchSet>
{
// ??[[__[[_ + (char)0x00 + {{ + (char)0x0 + (char)0x00 + {{ + (char)0x00 + (char)0x00 + (char)0x00 + (char)0x00 + (char)0x0 + (char)0x00 + (char)0x00 + (char)0x00 + (char)0x00 + ?;??;??
new(new byte?[]
{
0x3F, 0x3F, 0x5B, 0x5B, 0x5F, 0x5F, 0x5B, 0x5B,
0x5F, 0x00, 0x7B, 0x7B, 0x00, 0x00, 0x7B, 0x7B,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x20, 0x3F, 0x3B, 0x3F, 0x3F, 0x3B, 0x3F,
0x3F
}, "EXE Stealth"),
};
// ??[[__[[_ + (char)0x00 + {{ + (char)0x0 + (char)0x00 + {{ + (char)0x00 + (char)0x00 + (char)0x00 + (char)0x00 + (char)0x0 + (char)0x00 + (char)0x00 + (char)0x00 + (char)0x00 + ?;??;??
new(new byte?[]
{
0x3F, 0x3F, 0x5B, 0x5B, 0x5F, 0x5F, 0x5B, 0x5B,
0x5F, 0x00, 0x7B, 0x7B, 0x00, 0x00, 0x7B, 0x7B,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x20, 0x3F, 0x3B, 0x3F, 0x3F, 0x3B, 0x3F,
0x3F
}, "EXE Stealth"),
};
return MatchUtil.GetFirstMatch(file, fileContent, contentMatchSets, includeDebug);
}
return null;
return MatchUtil.GetFirstMatch(file, fileContent, contentMatchSets, includeDebug);
}
/// <inheritdoc/>
@@ -57,18 +56,17 @@ namespace BinaryObjectScanner.Packer
// `ExeStealth V2 Shareware not for public - This text not in registered version - www.webtoolmaster.com`
// Get the ExeS/EXES section, if it exists
bool exesSection = pex.ContainsSection("ExeS", exact: true) || pex.ContainsSection("EXES", exact: true);
if (exesSection)
if (pex.ContainsSection("ExeS", exact: true))
return "EXE Stealth 2.41-2.75";
if (pex.ContainsSection("EXES", exact: true))
return "EXE Stealth 2.41-2.75";
// Get the mtw section, if it exists
bool mtwSection = pex.ContainsSection("mtw", exact: true);
if (mtwSection)
if (pex.ContainsSection("mtw", exact: true))
return "EXE Stealth 1.1";
// Get the rsrr section, if it exists
bool rsrrSection = pex.ContainsSection("rsrr", exact: true);
if (rsrrSection)
if (pex.ContainsSection("rsrr", exact: true))
return "EXE Stealth 2.76";
return null;

View File

@@ -0,0 +1,139 @@
using System;
using System.IO;
using BinaryObjectScanner.Interfaces;
using SabreTools.Matching;
using SabreTools.Serialization.Wrappers;
namespace BinaryObjectScanner.Packer
{
/// <summary>
/// Though not technically a packer, this detection is for any executables that include
/// archives in their resources in some uncompressed manner to be used at runtime.
/// </summary>
public class EmbeddedArchive : IExtractableExecutable<PortableExecutable>
{
/// <inheritdoc/>
public string? CheckExecutable(string file, PortableExecutable pex, bool includeDebug)
{
// Get the sections from the executable, if possible
var sections = pex.Model.SectionTable;
if (sections == null)
return null;
// Get the resources that have a PKZIP signature
if (pex.ResourceData != null)
{
foreach (var value in pex.ResourceData.Values)
{
if (value == null || value is not byte[] ba)
continue;
if (!ba.StartsWith(SabreTools.Models.PKZIP.Constants.LocalFileHeaderSignatureBytes))
continue;
return "Embedded Archive";
}
}
// Check the overlay, if it exists
if (pex.OverlayData != null && pex.OverlayData.Length > 0)
{
if (pex.OverlayData.StartsWith(SabreTools.Models.PKZIP.Constants.LocalFileHeaderSignatureBytes))
return "Embedded Archive";
}
return null;
}
/// <inheritdoc/>
public bool Extract(string file, PortableExecutable pex, string outDir, bool includeDebug)
{
bool overlay = ExtractFromOverlay(pex, outDir, includeDebug);
bool resources = ExtractFromResources(pex, outDir, includeDebug);
return overlay || resources;
}
/// <summary>
/// Extract archive data from the overlay
/// </summary>
private static bool ExtractFromOverlay(PortableExecutable pex, string outDir, bool includeDebug)
{
try
{
// Get the overlay data for easier reading
var overlayData = pex.OverlayData;
if (overlayData == null)
return false;
// Only process the overlay if it has an archive signature
if (!overlayData.StartsWith(SabreTools.Models.PKZIP.Constants.LocalFileHeaderSignatureBytes))
return false;
// Create the temp filename
string tempFile = $"embedded_overlay.zip";
tempFile = Path.Combine(outDir, tempFile);
var directoryName = Path.GetDirectoryName(tempFile);
if (directoryName != null && !Directory.Exists(directoryName))
Directory.CreateDirectory(directoryName);
// Write the resource data to a temp file
using var tempStream = File.Open(tempFile, FileMode.Create, FileAccess.Write, FileShare.ReadWrite);
tempStream?.Write(overlayData, 0, overlayData.Length);
return true;
}
catch (Exception ex)
{
if (includeDebug) Console.WriteLine(ex);
return false;
}
}
/// <summary>
/// Extract archive data from the resources
/// </summary>
private static bool ExtractFromResources(PortableExecutable pex, string outDir, bool includeDebug)
{
try
{
// If there are no resources
if (pex.ResourceData == null)
return false;
// Get the resources that have an archive signature
int i = 0;
foreach (var value in pex.ResourceData.Values)
{
if (value == null || value is not byte[] ba)
continue;
if (!ba.StartsWith(SabreTools.Models.PKZIP.Constants.LocalFileHeaderSignatureBytes))
continue;
try
{
// Create the temp filename
string tempFile = $"embedded_resource_{i++}.zip";
tempFile = Path.Combine(outDir, tempFile);
var directoryName = Path.GetDirectoryName(tempFile);
if (directoryName != null && !Directory.Exists(directoryName))
Directory.CreateDirectory(directoryName);
// Write the resource data to a temp file
using var tempStream = File.Open(tempFile, FileMode.Create, FileAccess.Write, FileShare.ReadWrite);
tempStream?.Write(ba, 0, ba.Length);
}
catch (Exception ex)
{
if (includeDebug) Console.WriteLine(ex);
}
}
return true;
}
catch (Exception ex)
{
if (includeDebug) Console.WriteLine(ex);
return false;
}
}
}
}

View File

@@ -1,6 +1,5 @@
using System;
using System.IO;
using System.Linq;
using BinaryObjectScanner.Interfaces;
using SabreTools.Matching;
using SabreTools.Serialization.Wrappers;
@@ -22,14 +21,24 @@ namespace BinaryObjectScanner.Packer
return null;
// Get the resources that have an executable signature
if (pex.ResourceData?.Any(kvp => kvp.Value is byte[] ba
#if NET20
&& Extensions.StartsWith(ba, SabreTools.Models.MSDOS.Constants.SignatureBytes)) == true)
#else
&& ba.StartsWith(SabreTools.Models.MSDOS.Constants.SignatureBytes)) == true)
#endif
if (pex.ResourceData != null)
{
return "Embedded Executable";
foreach (var value in pex.ResourceData.Values)
{
if (value == null || value is not byte[] ba)
continue;
if (!ba.StartsWith(SabreTools.Models.MSDOS.Constants.SignatureBytes))
continue;
return "Embedded Executable";
}
}
// Check the overlay, if it exists
if (pex.OverlayData != null && pex.OverlayData.Length > 0)
{
if (pex.OverlayData.StartsWith(SabreTools.Models.MSDOS.Constants.SignatureBytes))
return "Embedded Executable";
}
return null;
@@ -37,6 +46,52 @@ namespace BinaryObjectScanner.Packer
/// <inheritdoc/>
public bool Extract(string file, PortableExecutable pex, string outDir, bool includeDebug)
{
bool overlay = ExtractFromOverlay(pex, outDir, includeDebug);
bool resources = ExtractFromResources(pex, outDir, includeDebug);
return overlay || resources;
}
/// <summary>
/// Extract executable data from the overlay
/// </summary>
private static bool ExtractFromOverlay(PortableExecutable pex, string outDir, bool includeDebug)
{
try
{
// Get the overlay data for easier reading
var overlayData = pex.OverlayData;
if (overlayData == null)
return false;
// Only process the overlay if it has an executable signature
if (!overlayData.StartsWith(SabreTools.Models.MSDOS.Constants.SignatureBytes))
return false;
// Create the temp filename
string tempFile = $"embedded_overlay.bin"; // exe/dll
tempFile = Path.Combine(outDir, tempFile);
var directoryName = Path.GetDirectoryName(tempFile);
if (directoryName != null && !Directory.Exists(directoryName))
Directory.CreateDirectory(directoryName);
// Write the resource data to a temp file
using var tempStream = File.Open(tempFile, FileMode.Create, FileAccess.Write, FileShare.ReadWrite);
tempStream?.Write(overlayData, 0, overlayData.Length);
return true;
}
catch (Exception ex)
{
if (includeDebug) Console.WriteLine(ex);
return false;
}
}
/// <summary>
/// Extract executable data from the resources
/// </summary>
private static bool ExtractFromResources(PortableExecutable pex, string outDir, bool includeDebug)
{
try
{
@@ -45,27 +100,18 @@ namespace BinaryObjectScanner.Packer
return false;
// Get the resources that have an executable signature
var resources = pex.ResourceData
.Where(kvp => kvp.Value != null && kvp.Value is byte[])
.Select(kvp => kvp.Value as byte[])
#if NET20
.Where(b => b != null && Extensions.StartsWith(b, SabreTools.Models.MSDOS.Constants.SignatureBytes))
#else
.Where(b => b != null && b.StartsWith(SabreTools.Models.MSDOS.Constants.SignatureBytes))
#endif
.ToList();
for (int i = 0; i < resources.Count; i++)
int i = 0;
foreach (var value in pex.ResourceData.Values)
{
if (value == null || value is not byte[] ba)
continue;
if (!ba.StartsWith(SabreTools.Models.MSDOS.Constants.SignatureBytes))
continue;
try
{
// Get the resource data
var data = resources[i];
if (data == null)
continue;
// Create the temp filename
string tempFile = $"embedded_resource_{i}.bin";
string tempFile = $"embedded_resource_{i++}.bin"; // exe/dll
tempFile = Path.Combine(outDir, tempFile);
var directoryName = Path.GetDirectoryName(tempFile);
if (directoryName != null && !Directory.Exists(directoryName))
@@ -73,7 +119,7 @@ namespace BinaryObjectScanner.Packer
// Write the resource data to a temp file
using var tempStream = File.Open(tempFile, FileMode.Create, FileAccess.Write, FileShare.ReadWrite);
tempStream?.Write(data, 0, data.Length);
tempStream?.Write(ba, 0, ba.Length);
}
catch (Exception ex)
{

View File

@@ -21,11 +21,10 @@ namespace BinaryObjectScanner.Packer
// This check may be overly limiting, as it excludes the sample provided to DiE (https://github.com/horsicq/Detect-It-Easy/issues/102).
// TODO: Find further samples and invesitgate if the "peC" section is only present on specific versions.
bool peCSection = pex.ContainsSection("peC", exact: true);
bool importTableMatch = Array.Exists(pex.Model.ImportTable?.ImportDirectoryTable ?? [],
idte => idte?.Name == "KeRnEl32.dLl");
if (peCSection && importTableMatch)
if (pex.ContainsSection("peC", exact: true) && importTableMatch)
return "HyperTech CrackProof";
return null;

View File

@@ -15,13 +15,17 @@ namespace BinaryObjectScanner.Packer
public string? CheckExecutable(string file, NewExecutable nex, bool includeDebug)
{
// Check for "Inno" in the reserved words
if (nex.Model.Stub?.Header?.Reserved2?[4] == 0x6E49 && nex.Model.Stub?.Header?.Reserved2?[5] == 0x6F6E)
var reserved2 = nex.Model.Stub?.Header?.Reserved2;
if (reserved2 != null && reserved2.Length > 5)
{
string version = GetOldVersion(file, nex);
if (!string.IsNullOrEmpty(version))
return $"Inno Setup {version}";
return "Inno Setup (Unknown Version)";
if (reserved2[4] == 0x6E49 && reserved2[5] == 0x6F6E)
{
string version = GetOldVersion(file, nex);
if (!string.IsNullOrEmpty(version))
return $"Inno Setup {version}";
return "Inno Setup (Unknown Version)";
}
}
return null;
@@ -78,8 +82,8 @@ namespace BinaryObjectScanner.Packer
return MatchUtil.GetFirstMatch(file, data, matchers, false) ?? "Unknown 1.X";
}
return "Unknown 1.X";
return "Unknown 1.X";
}
}
}

View File

@@ -33,7 +33,7 @@ namespace BinaryObjectScanner.Packer
return false;
}
private string GetVersion(PortableExecutable pex)
private static string GetVersion(PortableExecutable pex)
{
// Check the internal versions
var version = pex.GetInternalVersion();

View File

@@ -51,7 +51,7 @@ namespace BinaryObjectScanner.Packer
return false;
}
private string GetVersion(PortableExecutable pex)
private static string GetVersion(PortableExecutable pex)
{
// Check the internal versions
var version = pex.GetInternalVersion();

View File

@@ -14,9 +14,9 @@ namespace BinaryObjectScanner.Packer
if (sections == null)
return null;
var description = pex.AssemblyDescription;
if (!string.IsNullOrEmpty(description) && description!.StartsWith("Nullsoft Install System"))
return $"NSIS {description.Substring("Nullsoft Install System".Length).Trim()}";
var name = pex.AssemblyDescription;
if (name?.StartsWith("Nullsoft Install System") == true)
return $"NSIS {name.Substring("Nullsoft Install System".Length).Trim()}";
// Get the .data/DATA section strings, if they exist
var strs = pex.GetFirstSectionStrings(".data") ?? pex.GetFirstSectionStrings("DATA");

View File

@@ -26,8 +26,7 @@ namespace BinaryObjectScanner.Packer
// Get the .neolit section, if it exists.
// TODO: Check if this section is also present in NeoLite 1.X.
bool neolitSection = pex.ContainsSection(".neolit", exact: true);
if (neolitSection)
if (pex.ContainsSection(".neolit", exact: true))
return "NeoLite";
// If more specific or additional checks are needed, "NeoLite Executable File Compressor" should be present

View File

@@ -23,13 +23,12 @@ namespace BinaryObjectScanner.Packer
// on the data in the file. This may be related to information in other fields
// Get the pec1 section, if it exists
bool pec1Section = pex.ContainsSection("pec1", exact: true);
if (pec1Section)
if (pex.ContainsSection("pec1", exact: true))
return "PE Compact v1.x";
// Get the PEC2 section, if it exists -- TODO: Verify this comment since it's pulling the .text section
var textSection = pex.GetFirstSection(".text", exact: true);
if (textSection != null && textSection.PointerToRelocations == 0x32434550)
if (textSection?.PointerToRelocations == 0x32434550)
{
if (textSection.PointerToLinenumbers != 0)
return $"PE Compact v{textSection.PointerToLinenumbers} (internal version)";

View File

@@ -16,8 +16,7 @@ namespace BinaryObjectScanner.Packer
return null;
// Get the .petite section, if it exists -- TODO: Is there a version number that can be found?
bool petiteSection = pex.ContainsSection(".petite", exact: true);
if (petiteSection)
if (pex.ContainsSection(".petite", exact: true))
return "PEtite";
return null;

View File

@@ -43,7 +43,7 @@ namespace BinaryObjectScanner.Packer
return false;
}
private string GetVersion(PortableExecutable pex)
private static string GetVersion(PortableExecutable pex)
{
// Check the product version explicitly
var version = pex.ProductVersion;

View File

@@ -1,4 +1,3 @@
using System.Linq;
using BinaryObjectScanner.Interfaces;
using SabreTools.Serialization.Wrappers;
@@ -37,7 +36,7 @@ namespace BinaryObjectScanner.Packer
return "7-Zip SFX";
// If any dialog boxes match
if (pex.FindDialogByTitle("7-Zip self-extracting archive").Any())
if (pex.FindDialogByTitle("7-Zip self-extracting archive").Count > 0)
return "7-Zip SFX";
return null;

View File

@@ -16,9 +16,7 @@ namespace BinaryObjectScanner.Packer
return null;
// Get the .shrink0 and .shrink2 sections, if they exist -- TODO: Confirm if both are needed or either/or is fine
bool shrink0Section = pex.ContainsSection(".shrink0", true);
bool shrink2Section = pex.ContainsSection(".shrink2", true);
if (shrink0Section || shrink2Section)
if (pex.ContainsSection(".shrink0", true) || pex.ContainsSection(".shrink2", true))
return "Shrinker";
return null;

View File

@@ -73,10 +73,13 @@ namespace BinaryObjectScanner.Packer
{
// Check the normal version location first
int index = positions[0] - 5;
string versionString = Encoding.ASCII.GetString(fileContent, index, 4);
if (char.IsNumber(versionString[0]))
return versionString;
if (index >= 0 && index < fileContent.Length - 4)
{
string versionString = Encoding.ASCII.GetString(fileContent, index, 4);
if (char.IsNumber(versionString[0]))
return versionString;
}
// Check for the old-style string
//
// Example:
@@ -84,9 +87,12 @@ namespace BinaryObjectScanner.Packer
// $Id: UPX 1.02 Copyright (C) 1996-2000 the UPX Team. All Rights Reserved. $
// UPX!
index = positions[0] - 67;
versionString = Encoding.ASCII.GetString(fileContent, index, 4);
if (char.IsNumber(versionString[0]))
return versionString;
if (index >= 0 && index < fileContent.Length - 4)
{
string versionString = Encoding.ASCII.GetString(fileContent, index, 4);
if (char.IsNumber(versionString[0]))
return versionString;
}
return "(Unknown Version)";
}

View File

@@ -1,4 +1,3 @@
using System.Linq;
using BinaryObjectScanner.Interfaces;
using SabreTools.Serialization.Wrappers;
@@ -18,8 +17,7 @@ namespace BinaryObjectScanner.Packer
if (name?.Contains("WinRAR archiver") == true)
return "WinRAR SFX";
var resources = pex.FindDialogByTitle("WinRAR self-extracting archive");
if (resources.Any())
if (pex.FindDialogByTitle("WinRAR self-extracting archive").Count > 0)
return "WinRAR SFX";
return null;

View File

@@ -1,4 +1,4 @@
using System.Linq;
using System;
using System.Text;
using BinaryObjectScanner.Interfaces;
using SabreTools.Serialization.Wrappers;
@@ -14,13 +14,15 @@ namespace BinaryObjectScanner.Packer
if (nex.Model.ResidentNameTable == null)
return null;
// Get the resident and non-resident name table strings
var rntStrs = Array.ConvertAll(nex.Model.ResidentNameTable,
rnte => rnte?.NameString == null ? string.Empty : Encoding.ASCII.GetString(rnte.NameString));
var nrntStrs = Array.ConvertAll(nex.Model.NonResidentNameTable ?? [],
nrnte => nrnte?.NameString == null ? string.Empty : Encoding.ASCII.GetString(nrnte.NameString));
// Check for the WinZip name strings
bool winZipNameFound = nex.Model.ResidentNameTable
.Select(rnte => rnte?.NameString == null ? string.Empty : Encoding.ASCII.GetString(rnte.NameString))
.Any(s => s.Contains("WZ-SE-01"));
winZipNameFound |= nex.Model.NonResidentNameTable?
.Select(nrnte => nrnte?.NameString == null ? string.Empty : Encoding.ASCII.GetString(nrnte.NameString))
.Any(s => s.Contains("WinZip(R) Self-Extractor")) ?? false;
bool winZipNameFound = Array.Exists(rntStrs, s => s.Contains("WZ-SE-01"));
winZipNameFound |= Array.Exists(nrntStrs, s => s.Contains("WinZip(R) Self-Extractor"));
// If we didn't find it
if (!winZipNameFound)
@@ -646,8 +648,10 @@ namespace BinaryObjectScanner.Packer
string assemblyVersion = pex.AssemblyVersion ?? "Unknown Version";
// Standard
if (sfxFileName == "VW95SE.SFX" || sfxFileName == "ST32E.SFX"
|| sfxFileName == "WZIPSE32.exe" || sfxFileName == "SI32LPG.SFX"
if (sfxFileName == "VW95SE.SFX"
|| sfxFileName == "ST32E.SFX"
|| sfxFileName == "WZIPSE32.exe"
|| sfxFileName == "SI32LPG.SFX"
|| sfxFileName == "ST32E.WZE")
{
return sfxTimeDateStamp switch
@@ -670,8 +674,10 @@ namespace BinaryObjectScanner.Packer
}
// Personal Edition
if (sfxFileName == "VW95LE.SFX" || sfxFileName == "PE32E.SFX"
|| sfxFileName == "wzsepe32.exe" || sfxFileName == "SI32PE.SFX"
if (sfxFileName == "VW95LE.SFX"
|| sfxFileName == "PE32E.SFX"
|| sfxFileName == "wzsepe32.exe"
|| sfxFileName == "SI32PE.SFX"
|| sfxFileName == "SI32LPE.SFX")
{
return sfxTimeDateStamp switch
@@ -713,7 +719,8 @@ namespace BinaryObjectScanner.Packer
}
// Software Installation
else if (sfxFileName == "VW95SRE.SFX" || sfxFileName == "SI32E.SFX"
else if (sfxFileName == "VW95SRE.SFX"
|| sfxFileName == "SI32E.SFX"
|| sfxFileName == "SI32E.WZE")
{
return sfxTimeDateStamp switch

View File

@@ -156,11 +156,7 @@ namespace BinaryObjectScanner.Packer
// If the first entry is PKZIP, we assume it's an embedded zipfile
var magic = overlayData.ReadBytes(ref overlayOffset, 4); overlayOffset -= 4;
#if NET20
bool pkzip = Extensions.StartsWith(magic, new byte?[] { (byte)'P', (byte)'K' });
#else
bool pkzip = magic?.StartsWith(new byte?[] { (byte)'P', (byte)'K' }) ?? false;
#endif
// Create the output directory
Directory.CreateDirectory(outDir);
@@ -192,7 +188,7 @@ namespace BinaryObjectScanner.Packer
/// </summary>
/// <param name="nex">New executable to check</param>
/// <returns>True if it matches a known version, false otherwise</returns>
private FormatProperty? MatchesNEVersion(NewExecutable nex)
private static FormatProperty? MatchesNEVersion(NewExecutable nex)
{
// TODO: Offset is _not_ the EXE header address, rather where the data starts. Fix this.
switch (nex.Model.Stub?.Header?.NewExeHeaderAddr)
@@ -249,7 +245,7 @@ namespace BinaryObjectScanner.Packer
/// </summary>
/// <param name="pex">Portable executable to check</param>
/// <returns>True if it matches a known version, false otherwise</returns>
private FormatProperty? GetPEFormat(PortableExecutable pex)
private static FormatProperty? GetPEFormat(PortableExecutable pex)
{
if (pex.OverlayAddress == 0x6e00
&& pex.GetFirstSection(".text")?.VirtualSize == 0x3cf4

View File

@@ -8,16 +8,6 @@ using System.Diagnostics;
namespace System
{
/// <summary>Defines a provider for progress updates.</summary>
/// <typeparam name="T">The type of progress update value.</typeparam>
/// <see href="https://github.com/dotnet/runtime/blob/main/src/libraries/System.Private.CoreLib/src/System/IProgress.cs"/>
public interface IProgress<in T>
{
/// <summary>Reports a progress update.</summary>
/// <param name="value">The value of the updated progress.</param>
void Report(T value);
}
/// <summary>
/// Provides an IProgress{T} that invokes callbacks for each reported progress value.
/// </summary>

View File

@@ -1,5 +1,4 @@
using System.Collections.Generic;
using System.Linq;
using System.Text;
using BinaryObjectScanner.Interfaces;
using SabreTools.Matching;
@@ -14,24 +13,23 @@ namespace BinaryObjectScanner.Protection
/// <inheritdoc/>
public string? CheckContents(string file, byte[] fileContent, bool includeDebug)
{
// Only allow during debug
if (!includeDebug)
return null;
// TODO: Obtain a sample to find where this string is in a typical executable
if (includeDebug)
var contentMatchSets = new List<ContentMatchSet>
{
var contentMatchSets = new List<ContentMatchSet>
// " " + (char)0xC2 + (char)0x16 + (char)0x00 + (char)0xA8 + (char)0xC1 + (char)0x16 + (char)0x00 + (char)0xB8 + (char)0xC1 + (char)0x16 + (char)0x00 + (char)0x86 + (char)0xC8 + (char)0x16 + (char)0x00 + (char)0x9A + (char)0xC1 + (char)0x16 + (char)0x00 + (char)0x10 + (char)0xC2 + (char)0x16 + (char)0x00
new(new byte?[]
{
// " " + (char)0xC2 + (char)0x16 + (char)0x00 + (char)0xA8 + (char)0xC1 + (char)0x16 + (char)0x00 + (char)0xB8 + (char)0xC1 + (char)0x16 + (char)0x00 + (char)0x86 + (char)0xC8 + (char)0x16 + (char)0x00 + (char)0x9A + (char)0xC1 + (char)0x16 + (char)0x00 + (char)0x10 + (char)0xC2 + (char)0x16 + (char)0x00
new(new byte?[]
{
0x20, 0xC2, 0x16, 0x00, 0xA8, 0xC1, 0x16, 0x00,
0xB8, 0xC1, 0x16, 0x00, 0x86, 0xC8, 0x16, 0x00,
0x9A, 0xC1, 0x16, 0x00, 0x10, 0xC2, 0x16, 0x00
}, "ActiveMARK 5 (Unconfirmed - Please report to us on Github)"),
};
0x20, 0xC2, 0x16, 0x00, 0xA8, 0xC1, 0x16, 0x00,
0xB8, 0xC1, 0x16, 0x00, 0x86, 0xC8, 0x16, 0x00,
0x9A, 0xC1, 0x16, 0x00, 0x10, 0xC2, 0x16, 0x00
}, "ActiveMARK 5 (Unconfirmed - Please report to us on Github)"),
};
return MatchUtil.GetFirstMatch(file, fileContent, contentMatchSets, includeDebug);
}
return null;
return MatchUtil.GetFirstMatch(file, fileContent, contentMatchSets, includeDebug);
}
/// <inheritdoc/>
@@ -45,47 +43,25 @@ namespace BinaryObjectScanner.Protection
// Get the entry point data, if it exists
if (pex.EntryPointData != null)
{
#if NET20
// Found in "Zuma.exe"
if (Extensions.StartsWith(pex.EntryPointData, new byte?[] { 0x89, 0x25, 0x04, 0xF0, 0x86, 0x00, 0x68, 0x30 }))
if (pex.EntryPointData.StartsWith(new byte?[] { 0x89, 0x25, 0x04, 0xF0, 0x86, 0x00, 0x68, 0x30 }))
return "ActiveMark v5.3.1078 (Packer Version)";
// https://raw.githubusercontent.com/wolfram77web/app-peid/master/userdb.txt
else if (Extensions.StartsWith(pex.EntryPointData, new byte?[] { 0x89, 0x25, null, null, null, null, 0xEB }))
else if (pex.EntryPointData.StartsWith(new byte?[] { 0x89, 0x25, null, null, null, null, 0xEB }))
return "ActiveMark -> Trymedia Systems Inc. (Unconfirmed - Please report to us on Github)";
else if (Extensions.StartsWith(pex.EntryPointData, new byte?[] { 0x89, 0x25, null, null, null, null, 0x33, 0xED, 0x55, 0x8B, 0xEC, 0xE8, null, null, null, null, 0x8B, 0xD0, 0x81, 0xE2, 0xFF, 0x00, 0x00, 0x00, 0x89, 0x15, null, null, null, null, 0x8B, 0xD0, 0xC1, 0xEA, 0x08, 0x81, 0xE2, 0xFF, 0x00, 0x00, 0x00, 0xA3, null, null, null, null, 0xD1, 0xE0, 0x0F, 0x93, 0xC3, 0x33, 0xC0, 0x8A, 0xC3, 0xA3, null, null, null, null, 0x68, 0xFF, 0x00, 0x00, 0x00, 0xE8, null, null, null, null, 0x6A, 0x00, 0xE8, null, null, null, null, 0xA3, null, null, null, null, 0xBB, null, null, null, null, 0xC7, 0x03, 0x44, 0x00, 0x00, 0x00 }))
else if (pex.EntryPointData.StartsWith(new byte?[] { 0x89, 0x25, null, null, null, null, 0x33, 0xED, 0x55, 0x8B, 0xEC, 0xE8, null, null, null, null, 0x8B, 0xD0, 0x81, 0xE2, 0xFF, 0x00, 0x00, 0x00, 0x89, 0x15, null, null, null, null, 0x8B, 0xD0, 0xC1, 0xEA, 0x08, 0x81, 0xE2, 0xFF, 0x00, 0x00, 0x00, 0xA3, null, null, null, null, 0xD1, 0xE0, 0x0F, 0x93, 0xC3, 0x33, 0xC0, 0x8A, 0xC3, 0xA3, null, null, null, null, 0x68, 0xFF, 0x00, 0x00, 0x00, 0xE8, null, null, null, null, 0x6A, 0x00, 0xE8, null, null, null, null, 0xA3, null, null, null, null, 0xBB, null, null, null, null, 0xC7, 0x03, 0x44, 0x00, 0x00, 0x00 }))
return "ActiveMark -> Trymedia Systems Inc. (Unconfirmed - Please report to us on Github)";
else if (Extensions.StartsWith(pex.EntryPointData, new byte?[] { 0x20, 0x2D, 0x2D, 0x4D, 0x50, 0x52, 0x4D, 0x4D, 0x47, 0x56, 0x41, 0x2D, 0x2D, 0x00, 0x75, 0x73, 0x65, 0x72, 0x33, 0x32, 0x2E, 0x64, 0x6C, 0x6C, 0x00, 0x4D, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x42, 0x6F, 0x78, 0x41, 0x00, 0x54, 0x68, 0x69, 0x73, 0x20, 0x61, 0x70, 0x70, 0x6C, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x63, 0x61, 0x6E, 0x6E, 0x6F, 0x74, 0x20, 0x72, 0x75, 0x6E, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x61, 0x6E, 0x20, 0x61, 0x63, 0x74, 0x69, 0x76, 0x65, 0x20, 0x64, 0x65, 0x62, 0x75, 0x67 }))
else if (pex.EntryPointData.StartsWith(new byte?[] { 0x20, 0x2D, 0x2D, 0x4D, 0x50, 0x52, 0x4D, 0x4D, 0x47, 0x56, 0x41, 0x2D, 0x2D, 0x00, 0x75, 0x73, 0x65, 0x72, 0x33, 0x32, 0x2E, 0x64, 0x6C, 0x6C, 0x00, 0x4D, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x42, 0x6F, 0x78, 0x41, 0x00, 0x54, 0x68, 0x69, 0x73, 0x20, 0x61, 0x70, 0x70, 0x6C, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x63, 0x61, 0x6E, 0x6E, 0x6F, 0x74, 0x20, 0x72, 0x75, 0x6E, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x61, 0x6E, 0x20, 0x61, 0x63, 0x74, 0x69, 0x76, 0x65, 0x20, 0x64, 0x65, 0x62, 0x75, 0x67 }))
return "ActiveMARK 5.x -> Trymedia Systems Inc. (h) (Unconfirmed - Please report to us on Github)";
else if (Extensions.StartsWith(pex.EntryPointData, new byte?[] { 0x20, 0x2D, 0x2D, 0x4D, 0x50, 0x52, 0x4D, 0x4D, 0x47, 0x56, 0x41, 0x2D, 0x2D, 0x00, 0x75, 0x73, 0x65, 0x72, 0x33, 0x32, 0x2E, 0x64, 0x6C, 0x6C, 0x00, 0x4D, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x42, 0x6F, 0x78, 0x41, 0x00, 0x54, 0x68, 0x69, 0x73, 0x20, 0x61, 0x70, 0x70, 0x6C, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x63, 0x61, 0x6E, 0x6E, 0x6F, 0x74, 0x20, 0x72, 0x75, 0x6E, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x61, 0x6E, 0x20, 0x61, 0x63, 0x74, 0x69, 0x76, 0x65, 0x20, 0x64, 0x65, 0x62, 0x75, 0x67, 0x67, 0x65, 0x72, 0x20, 0x69, 0x6E, 0x20, 0x6D, 0x65, 0x6D, 0x6F, 0x72, 0x79, 0x2E, 0x0D, 0x0A, 0x50, 0x6C, 0x65, 0x61, 0x73, 0x65, 0x20, 0x75, 0x6E, 0x6C, 0x6F, 0x61, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x64, 0x65, 0x62, 0x75, 0x67, 0x67, 0x65, 0x72, 0x20, 0x61, 0x6E, 0x64, 0x20, 0x72, 0x65, 0x73, 0x74, 0x61, 0x72, 0x74, 0x20, 0x74, 0x68, 0x65, 0x20, 0x61, 0x70, 0x70, 0x6C, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x2E, 0x00, 0x57, 0x61, 0x72, 0x6E, 0x69, 0x6E, 0x67 }))
else if (pex.EntryPointData.StartsWith(new byte?[] { 0x20, 0x2D, 0x2D, 0x4D, 0x50, 0x52, 0x4D, 0x4D, 0x47, 0x56, 0x41, 0x2D, 0x2D, 0x00, 0x75, 0x73, 0x65, 0x72, 0x33, 0x32, 0x2E, 0x64, 0x6C, 0x6C, 0x00, 0x4D, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x42, 0x6F, 0x78, 0x41, 0x00, 0x54, 0x68, 0x69, 0x73, 0x20, 0x61, 0x70, 0x70, 0x6C, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x63, 0x61, 0x6E, 0x6E, 0x6F, 0x74, 0x20, 0x72, 0x75, 0x6E, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x61, 0x6E, 0x20, 0x61, 0x63, 0x74, 0x69, 0x76, 0x65, 0x20, 0x64, 0x65, 0x62, 0x75, 0x67, 0x67, 0x65, 0x72, 0x20, 0x69, 0x6E, 0x20, 0x6D, 0x65, 0x6D, 0x6F, 0x72, 0x79, 0x2E, 0x0D, 0x0A, 0x50, 0x6C, 0x65, 0x61, 0x73, 0x65, 0x20, 0x75, 0x6E, 0x6C, 0x6F, 0x61, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x64, 0x65, 0x62, 0x75, 0x67, 0x67, 0x65, 0x72, 0x20, 0x61, 0x6E, 0x64, 0x20, 0x72, 0x65, 0x73, 0x74, 0x61, 0x72, 0x74, 0x20, 0x74, 0x68, 0x65, 0x20, 0x61, 0x70, 0x70, 0x6C, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x2E, 0x00, 0x57, 0x61, 0x72, 0x6E, 0x69, 0x6E, 0x67 }))
return "ActiveMARK 5.x -> Trymedia Systems,Inc. (Unconfirmed - Please report to us on Github)";
else if (Extensions.StartsWith(pex.EntryPointData, new byte?[] { 0x79, 0x11, 0x7F, 0xAB, 0x9A, 0x4A, 0x83, 0xB5, 0xC9, 0x6B, 0x1A, 0x48, 0xF9, 0x27, 0xB4, 0x25 }))
else if (pex.EntryPointData.StartsWith(new byte?[] { 0x79, 0x11, 0x7F, 0xAB, 0x9A, 0x4A, 0x83, 0xB5, 0xC9, 0x6B, 0x1A, 0x48, 0xF9, 0x27, 0xB4, 0x25 }))
return "ActiveMARK[TM] (Unconfirmed - Please report to us on Github)";
else if (Extensions.StartsWith(pex.EntryPointData, new byte?[] { 0x79, 0x07, 0x0F, 0xB7, 0x07, 0x47, 0x50, 0x47, 0xB9, 0x57, 0x48, 0xF2, 0xAE, 0x55, 0xFF, 0x96, 0x84, null, 0x00, 0x00, 0x09, 0xC0, 0x74, 0x07, 0x89, 0x03, 0x83, 0xC3, 0x04, 0xEB, 0xD8, 0xFF, 0x96, 0x88, null, 0x00, 0x00, 0x61, 0xE9, null, null, null, 0xFF }))
else if (pex.EntryPointData.StartsWith(new byte?[] { 0x79, 0x07, 0x0F, 0xB7, 0x07, 0x47, 0x50, 0x47, 0xB9, 0x57, 0x48, 0xF2, 0xAE, 0x55, 0xFF, 0x96, 0x84, null, 0x00, 0x00, 0x09, 0xC0, 0x74, 0x07, 0x89, 0x03, 0x83, 0xC3, 0x04, 0xEB, 0xD8, 0xFF, 0x96, 0x88, null, 0x00, 0x00, 0x61, 0xE9, null, null, null, 0xFF }))
return "ActiveMARK[TM] R5.31.1140 -> Trymedia (Unconfirmed - Please report to us on Github)";
else if (Extensions.StartsWith(pex.EntryPointData, new byte?[] { 0xBE, 0x48, 0x01, 0x40, 0x00, 0xAD, 0x8B, 0xF8, 0x95, 0xA5, 0x33, 0xC0, 0x33, 0xC9, 0xAB, 0x48, 0xAB, 0xF7, 0xD8, 0xB1, 0x04, 0xF3, 0xAB, 0xC1, 0xE0, 0x0A, 0xB5, 0x1C, 0xF3, 0xAB, 0xAD, 0x50, 0x97, 0x51, 0xAD, 0x87, 0xF5, 0x58, 0x8D, 0x54, 0x86, 0x5C, 0xFF, 0xD5, 0x72, 0x5A, 0x2C, 0x03, 0x73, 0x02, 0xB0, 0x00, 0x3C, 0x07, 0x72, 0x02, 0x2C, 0x03, 0x50, 0x0F, 0xB6, 0x5F, 0xFF, 0xC1, 0xE3, 0x03, 0xB3, 0x00, 0x8D, 0x1C, 0x5B, 0x8D, 0x9C, 0x9E, 0x0C, 0x10, 0x00, 0x00, 0xB0, 0x01, 0x67, 0xE3, 0x29, 0x8B, 0xD7, 0x2B, 0x56, 0x0C, 0x8A, 0x2A, 0x33, 0xD2, 0x84, 0xE9, 0x0F, 0x95, 0xC6, 0x52, 0xFE, 0xC6, 0x8A, 0xD0, 0x8D, 0x14, 0x93, 0xFF, 0xD5, 0x5A, 0x9F, 0x12, 0xC0, 0xD0, 0xE9, 0x74, 0x0E, 0x9E, 0x1A, 0xF2, 0x74, 0xE4, 0xB4, 0x00, 0x33, 0xC9, 0xB5, 0x01, 0xFF, 0x55, 0xCC, 0x33, 0xC9, 0xE9, 0xDF, 0x00, 0x00, 0x00, 0x8B, 0x5E, 0x0C, 0x83, 0xC2, 0x30, 0xFF, 0xD5, 0x73, 0x50, 0x83, 0xC2, 0x30, 0xFF, 0xD5, 0x72, 0x1B, 0x83, 0xC2, 0x30, 0xFF, 0xD5, 0x72, 0x2B, 0x3C, 0x07, 0xB0, 0x09, 0x72, 0x02, 0xB0, 0x0B, 0x50, 0x8B, 0xC7, 0x2B, 0x46, 0x0C, 0xB1, 0x80, 0x8A, 0x00, 0xEB, 0xCF, 0x83, 0xC2, 0x60, 0xFF, 0xD5, 0x87, 0x5E, 0x10, 0x73, 0x0D, 0x83, 0xC2, 0x30, 0xFF, 0xD5, 0x87, 0x5E, 0x14, 0x73, 0x03, 0x87, 0x5E, 0x18, 0x3C, 0x07, 0xB0, 0x08, 0x72, 0x02, 0xB0, 0x0B, 0x50, 0x53, 0x8D, 0x96, 0x7C, 0x07, 0x00, 0x00, 0xFF, 0x55, 0xD0, 0x5B, 0x91, 0xEB, 0x77, 0x3C, 0x07, 0xB0, 0x07, 0x72, 0x02, 0xB0, 0x0A, 0x50, 0x87, 0x5E, 0x10, 0x87, 0x5E, 0x14, 0x89, 0x5E, 0x18, 0x8D, 0x96, 0xC4, 0x0B, 0x00, 0x00, 0xFF, 0x55, 0xD0, 0x50, 0x48 }))
else if (pex.EntryPointData.StartsWith(new byte?[] { 0xBE, 0x48, 0x01, 0x40, 0x00, 0xAD, 0x8B, 0xF8, 0x95, 0xA5, 0x33, 0xC0, 0x33, 0xC9, 0xAB, 0x48, 0xAB, 0xF7, 0xD8, 0xB1, 0x04, 0xF3, 0xAB, 0xC1, 0xE0, 0x0A, 0xB5, 0x1C, 0xF3, 0xAB, 0xAD, 0x50, 0x97, 0x51, 0xAD, 0x87, 0xF5, 0x58, 0x8D, 0x54, 0x86, 0x5C, 0xFF, 0xD5, 0x72, 0x5A, 0x2C, 0x03, 0x73, 0x02, 0xB0, 0x00, 0x3C, 0x07, 0x72, 0x02, 0x2C, 0x03, 0x50, 0x0F, 0xB6, 0x5F, 0xFF, 0xC1, 0xE3, 0x03, 0xB3, 0x00, 0x8D, 0x1C, 0x5B, 0x8D, 0x9C, 0x9E, 0x0C, 0x10, 0x00, 0x00, 0xB0, 0x01, 0x67, 0xE3, 0x29, 0x8B, 0xD7, 0x2B, 0x56, 0x0C, 0x8A, 0x2A, 0x33, 0xD2, 0x84, 0xE9, 0x0F, 0x95, 0xC6, 0x52, 0xFE, 0xC6, 0x8A, 0xD0, 0x8D, 0x14, 0x93, 0xFF, 0xD5, 0x5A, 0x9F, 0x12, 0xC0, 0xD0, 0xE9, 0x74, 0x0E, 0x9E, 0x1A, 0xF2, 0x74, 0xE4, 0xB4, 0x00, 0x33, 0xC9, 0xB5, 0x01, 0xFF, 0x55, 0xCC, 0x33, 0xC9, 0xE9, 0xDF, 0x00, 0x00, 0x00, 0x8B, 0x5E, 0x0C, 0x83, 0xC2, 0x30, 0xFF, 0xD5, 0x73, 0x50, 0x83, 0xC2, 0x30, 0xFF, 0xD5, 0x72, 0x1B, 0x83, 0xC2, 0x30, 0xFF, 0xD5, 0x72, 0x2B, 0x3C, 0x07, 0xB0, 0x09, 0x72, 0x02, 0xB0, 0x0B, 0x50, 0x8B, 0xC7, 0x2B, 0x46, 0x0C, 0xB1, 0x80, 0x8A, 0x00, 0xEB, 0xCF, 0x83, 0xC2, 0x60, 0xFF, 0xD5, 0x87, 0x5E, 0x10, 0x73, 0x0D, 0x83, 0xC2, 0x30, 0xFF, 0xD5, 0x87, 0x5E, 0x14, 0x73, 0x03, 0x87, 0x5E, 0x18, 0x3C, 0x07, 0xB0, 0x08, 0x72, 0x02, 0xB0, 0x0B, 0x50, 0x53, 0x8D, 0x96, 0x7C, 0x07, 0x00, 0x00, 0xFF, 0x55, 0xD0, 0x5B, 0x91, 0xEB, 0x77, 0x3C, 0x07, 0xB0, 0x07, 0x72, 0x02, 0xB0, 0x0A, 0x50, 0x87, 0x5E, 0x10, 0x87, 0x5E, 0x14, 0x89, 0x5E, 0x18, 0x8D, 0x96, 0xC4, 0x0B, 0x00, 0x00, 0xFF, 0x55, 0xD0, 0x50, 0x48 }))
return "ActiveMARK 5.x -> Trymedia Systems,Inc. (h) (Unconfirmed - Please report to us on Github)";
#else
// Found in "Zuma.exe"
if (Extensions.StartsWith(pex.EntryPointData, new byte?[] { 0x89, 0x25, 0x04, 0xF0, 0x86, 0x00, 0x68, 0x30 }))
return "ActiveMark v5.3.1078 (Packer Version)";
// https://raw.githubusercontent.com/wolfram77web/app-peid/master/userdb.txt
else if (Extensions.StartsWith(pex.EntryPointData, new byte?[] { 0x89, 0x25, null, null, null, null, 0xEB }))
return "ActiveMark -> Trymedia Systems Inc. (Unconfirmed - Please report to us on Github)";
else if (Extensions.StartsWith(pex.EntryPointData, new byte?[] { 0x89, 0x25, null, null, null, null, 0x33, 0xED, 0x55, 0x8B, 0xEC, 0xE8, null, null, null, null, 0x8B, 0xD0, 0x81, 0xE2, 0xFF, 0x00, 0x00, 0x00, 0x89, 0x15, null, null, null, null, 0x8B, 0xD0, 0xC1, 0xEA, 0x08, 0x81, 0xE2, 0xFF, 0x00, 0x00, 0x00, 0xA3, null, null, null, null, 0xD1, 0xE0, 0x0F, 0x93, 0xC3, 0x33, 0xC0, 0x8A, 0xC3, 0xA3, null, null, null, null, 0x68, 0xFF, 0x00, 0x00, 0x00, 0xE8, null, null, null, null, 0x6A, 0x00, 0xE8, null, null, null, null, 0xA3, null, null, null, null, 0xBB, null, null, null, null, 0xC7, 0x03, 0x44, 0x00, 0x00, 0x00 }))
return "ActiveMark -> Trymedia Systems Inc. (Unconfirmed - Please report to us on Github)";
else if (Extensions.StartsWith(pex.EntryPointData, new byte?[] { 0x20, 0x2D, 0x2D, 0x4D, 0x50, 0x52, 0x4D, 0x4D, 0x47, 0x56, 0x41, 0x2D, 0x2D, 0x00, 0x75, 0x73, 0x65, 0x72, 0x33, 0x32, 0x2E, 0x64, 0x6C, 0x6C, 0x00, 0x4D, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x42, 0x6F, 0x78, 0x41, 0x00, 0x54, 0x68, 0x69, 0x73, 0x20, 0x61, 0x70, 0x70, 0x6C, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x63, 0x61, 0x6E, 0x6E, 0x6F, 0x74, 0x20, 0x72, 0x75, 0x6E, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x61, 0x6E, 0x20, 0x61, 0x63, 0x74, 0x69, 0x76, 0x65, 0x20, 0x64, 0x65, 0x62, 0x75, 0x67 }))
return "ActiveMARK 5.x -> Trymedia Systems Inc. (h) (Unconfirmed - Please report to us on Github)";
else if (Extensions.StartsWith(pex.EntryPointData, new byte?[] { 0x20, 0x2D, 0x2D, 0x4D, 0x50, 0x52, 0x4D, 0x4D, 0x47, 0x56, 0x41, 0x2D, 0x2D, 0x00, 0x75, 0x73, 0x65, 0x72, 0x33, 0x32, 0x2E, 0x64, 0x6C, 0x6C, 0x00, 0x4D, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x42, 0x6F, 0x78, 0x41, 0x00, 0x54, 0x68, 0x69, 0x73, 0x20, 0x61, 0x70, 0x70, 0x6C, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x63, 0x61, 0x6E, 0x6E, 0x6F, 0x74, 0x20, 0x72, 0x75, 0x6E, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x61, 0x6E, 0x20, 0x61, 0x63, 0x74, 0x69, 0x76, 0x65, 0x20, 0x64, 0x65, 0x62, 0x75, 0x67, 0x67, 0x65, 0x72, 0x20, 0x69, 0x6E, 0x20, 0x6D, 0x65, 0x6D, 0x6F, 0x72, 0x79, 0x2E, 0x0D, 0x0A, 0x50, 0x6C, 0x65, 0x61, 0x73, 0x65, 0x20, 0x75, 0x6E, 0x6C, 0x6F, 0x61, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x64, 0x65, 0x62, 0x75, 0x67, 0x67, 0x65, 0x72, 0x20, 0x61, 0x6E, 0x64, 0x20, 0x72, 0x65, 0x73, 0x74, 0x61, 0x72, 0x74, 0x20, 0x74, 0x68, 0x65, 0x20, 0x61, 0x70, 0x70, 0x6C, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x2E, 0x00, 0x57, 0x61, 0x72, 0x6E, 0x69, 0x6E, 0x67 }))
return "ActiveMARK 5.x -> Trymedia Systems,Inc. (Unconfirmed - Please report to us on Github)";
else if (Extensions.StartsWith(pex.EntryPointData, new byte?[] { 0x79, 0x11, 0x7F, 0xAB, 0x9A, 0x4A, 0x83, 0xB5, 0xC9, 0x6B, 0x1A, 0x48, 0xF9, 0x27, 0xB4, 0x25 }))
return "ActiveMARK[TM] (Unconfirmed - Please report to us on Github)";
else if (Extensions.StartsWith(pex.EntryPointData, new byte?[] { 0x79, 0x07, 0x0F, 0xB7, 0x07, 0x47, 0x50, 0x47, 0xB9, 0x57, 0x48, 0xF2, 0xAE, 0x55, 0xFF, 0x96, 0x84, null, 0x00, 0x00, 0x09, 0xC0, 0x74, 0x07, 0x89, 0x03, 0x83, 0xC3, 0x04, 0xEB, 0xD8, 0xFF, 0x96, 0x88, null, 0x00, 0x00, 0x61, 0xE9, null, null, null, 0xFF }))
return "ActiveMARK[TM] R5.31.1140 -> Trymedia (Unconfirmed - Please report to us on Github)";
else if (Extensions.StartsWith(pex.EntryPointData, new byte?[] { 0xBE, 0x48, 0x01, 0x40, 0x00, 0xAD, 0x8B, 0xF8, 0x95, 0xA5, 0x33, 0xC0, 0x33, 0xC9, 0xAB, 0x48, 0xAB, 0xF7, 0xD8, 0xB1, 0x04, 0xF3, 0xAB, 0xC1, 0xE0, 0x0A, 0xB5, 0x1C, 0xF3, 0xAB, 0xAD, 0x50, 0x97, 0x51, 0xAD, 0x87, 0xF5, 0x58, 0x8D, 0x54, 0x86, 0x5C, 0xFF, 0xD5, 0x72, 0x5A, 0x2C, 0x03, 0x73, 0x02, 0xB0, 0x00, 0x3C, 0x07, 0x72, 0x02, 0x2C, 0x03, 0x50, 0x0F, 0xB6, 0x5F, 0xFF, 0xC1, 0xE3, 0x03, 0xB3, 0x00, 0x8D, 0x1C, 0x5B, 0x8D, 0x9C, 0x9E, 0x0C, 0x10, 0x00, 0x00, 0xB0, 0x01, 0x67, 0xE3, 0x29, 0x8B, 0xD7, 0x2B, 0x56, 0x0C, 0x8A, 0x2A, 0x33, 0xD2, 0x84, 0xE9, 0x0F, 0x95, 0xC6, 0x52, 0xFE, 0xC6, 0x8A, 0xD0, 0x8D, 0x14, 0x93, 0xFF, 0xD5, 0x5A, 0x9F, 0x12, 0xC0, 0xD0, 0xE9, 0x74, 0x0E, 0x9E, 0x1A, 0xF2, 0x74, 0xE4, 0xB4, 0x00, 0x33, 0xC9, 0xB5, 0x01, 0xFF, 0x55, 0xCC, 0x33, 0xC9, 0xE9, 0xDF, 0x00, 0x00, 0x00, 0x8B, 0x5E, 0x0C, 0x83, 0xC2, 0x30, 0xFF, 0xD5, 0x73, 0x50, 0x83, 0xC2, 0x30, 0xFF, 0xD5, 0x72, 0x1B, 0x83, 0xC2, 0x30, 0xFF, 0xD5, 0x72, 0x2B, 0x3C, 0x07, 0xB0, 0x09, 0x72, 0x02, 0xB0, 0x0B, 0x50, 0x8B, 0xC7, 0x2B, 0x46, 0x0C, 0xB1, 0x80, 0x8A, 0x00, 0xEB, 0xCF, 0x83, 0xC2, 0x60, 0xFF, 0xD5, 0x87, 0x5E, 0x10, 0x73, 0x0D, 0x83, 0xC2, 0x30, 0xFF, 0xD5, 0x87, 0x5E, 0x14, 0x73, 0x03, 0x87, 0x5E, 0x18, 0x3C, 0x07, 0xB0, 0x08, 0x72, 0x02, 0xB0, 0x0B, 0x50, 0x53, 0x8D, 0x96, 0x7C, 0x07, 0x00, 0x00, 0xFF, 0x55, 0xD0, 0x5B, 0x91, 0xEB, 0x77, 0x3C, 0x07, 0xB0, 0x07, 0x72, 0x02, 0xB0, 0x0A, 0x50, 0x87, 0x5E, 0x10, 0x87, 0x5E, 0x14, 0x89, 0x5E, 0x18, 0x8D, 0x96, 0xC4, 0x0B, 0x00, 0x00, 0xFF, 0x55, 0xD0, 0x50, 0x48 }))
return "ActiveMARK 5.x -> Trymedia Systems,Inc. (h) (Unconfirmed - Please report to us on Github)";
#endif
}
// Get the .data section strings, if they exist
@@ -101,11 +77,11 @@ namespace BinaryObjectScanner.Protection
// Get "REGISTRY, AMINTERNETPROTOCOL" resource items
var resources = pex.FindResourceByNamedType("REGISTRY, AMINTERNETPROTOCOL");
if (resources.Any())
if (resources.Count > 0)
{
bool match = resources
.Select(r => r == null ? string.Empty : Encoding.ASCII.GetString(r))
.Any(r => r.Contains("ActiveMARK"));
.ConvertAll(r => r == null ? string.Empty : Encoding.ASCII.GetString(r))
.FindIndex(r => r.Contains("ActiveMARK")) > -1;
if (match)
return "ActiveMARK";
}

View File

@@ -1,5 +1,4 @@
using System.Collections.Generic;
using System.Linq;
using BinaryObjectScanner.Interfaces;
using SabreTools.Matching;
using SabreTools.Matching.Content;
@@ -41,7 +40,7 @@ namespace BinaryObjectScanner.Protection
// Get string table resources
var resource = pex.FindStringTableByEntry("AegiSoft License Manager");
if (resource.Any())
if (resource.Count > 0)
return "AegiSoft License Manager";
// Get the .data/DATA section, if it exists
@@ -68,7 +67,7 @@ namespace BinaryObjectScanner.Protection
}
/// <inheritdoc/>
public IEnumerable<string> CheckDirectoryPath(string path, IEnumerable<string>? files)
public List<string> CheckDirectoryPath(string path, List<string>? files)
{
var matchers = new List<PathMatchSet>
{

View File

@@ -16,7 +16,7 @@ namespace BinaryObjectScanner.Protection
public class AlphaDVD : IPathCheck
{
/// <inheritdoc/>
public IEnumerable<string> CheckDirectoryPath(string path, IEnumerable<string>? files)
public List<string> CheckDirectoryPath(string path, List<string>? files)
{
var matchers = new List<PathMatchSet>
{

View File

@@ -69,9 +69,11 @@ namespace BinaryObjectScanner.Protection
{
if (strs.Exists(s => s.Contains("This Game is Japan Only")))
return "Alpha-ROM";
// Found in "Filechk.exe" in Redump entry 115358.
if (strs.Exists(s => s.Contains("AlphaCheck.exe")))
return "Alpha-ROM";
// Found in "Uninstall.exe" in Redump entry 115358.
if (strs.Exists(s => s.Contains("AlphaCheck.dat")))
return "Alpha-ROM";

View File

@@ -29,14 +29,13 @@ namespace BinaryObjectScanner.Protection
return null;
// Get the .nicode section, if it exists
bool nicodeSection = pex.ContainsSection(".nicode", exact: true);
if (nicodeSection)
if (pex.ContainsSection(".nicode", exact: true))
return "Armadillo";
// Loop through all "extension" sections -- usually .data1 or .text1
if (pex.SectionNames != null)
{
foreach (var sectionName in Array.FindAll(pex.SectionNames, s => s != null && s.EndsWith("1")))
foreach (var sectionName in Array.FindAll(pex.SectionNames ?? [], s => s != null && s.EndsWith("1")))
{
// Get the section strings, if they exist
var strs = pex.GetFirstSectionStrings(sectionName);

View File

@@ -13,7 +13,7 @@ namespace BinaryObjectScanner.Protection
public class Bitpool : IPathCheck
{
/// <inheritdoc/>
public IEnumerable<string> CheckDirectoryPath(string path, IEnumerable<string>? files)
public List<string> CheckDirectoryPath(string path, List<string>? files)
{
var matchers = new List<PathMatchSet>
{

View File

@@ -1,5 +1,4 @@
using System.Collections.Generic;
using System.Linq;
using BinaryObjectScanner.Interfaces;
using SabreTools.Matching;
using SabreTools.Matching.Paths;
@@ -74,20 +73,17 @@ namespace BinaryObjectScanner.Protection
return "ByteShield Component Module";
// Found in "LineRider2.exe" in Redump entry 6236
var stMatch = pex.FindStringTableByEntry("ByteShield");
if (stMatch.Any())
if (pex.FindStringTableByEntry("ByteShield").Count > 0)
return $"ByteShield Activation Client {pex.GetInternalVersion()}";
// Found in "LineRider2.exe" in Redump entry 6236
var dbMatch = pex.FindDialogByTitle("About ByteShield");
if (dbMatch.Any())
if (pex.FindDialogByTitle("About ByteShield").Count > 0)
return "ByteShield";
// TODO: See if the version number is anywhere else
// TODO: Parse the version number out of the dialog box item
// Found in "LineRider2.exe" in Redump entry 6236
dbMatch = pex.FindDialogBoxByItemTitle("ByteShield Version 1.0");
if (dbMatch.Any())
if (pex.FindDialogBoxByItemTitle("ByteShield Version 1.0").Count > 0)
return "ByteShield";
// Get the .data/DATA section strings, if they exist
@@ -130,7 +126,7 @@ namespace BinaryObjectScanner.Protection
}
/// <inheritdoc/>
public IEnumerable<string> CheckDirectoryPath(string path, IEnumerable<string>? files)
public List<string> CheckDirectoryPath(string path, List<string>? files)
{
// TODO: Investigate reference to "bbz650.tmp" in "Byteshield.dll" (Redump entry 6236)
// Files with the ".bbz" extension are associated with ByteShield, but the extenstion is known to be used in other places as well.

View File

@@ -69,31 +69,30 @@ namespace BinaryObjectScanner.Protection
/// <inheritdoc/>
public string? CheckContents(string file, byte[] fileContent, bool includeDebug)
{
// Only allow during debug
if (!includeDebug)
return null;
// TODO: Obtain a sample to find where this string is in a typical executable
if (includeDebug)
var contentMatchSets = new List<ContentMatchSet>
{
var contentMatchSets = new List<ContentMatchSet>
// TODO: Remove from here once it's confirmed that no PE executables contain this string
// CD-Cops, ver.
new(new byte?[]
{
// TODO: Remove from here once it's confirmed that no PE executables contain this string
// CD-Cops, ver.
new(new byte?[]
{
0x43, 0x44, 0x2D, 0x43, 0x6F, 0x70, 0x73, 0x2C,
0x20, 0x20, 0x76, 0x65, 0x72, 0x2E, 0x20
}, GetVersion, "CD-Cops (Unconfirmed - Please report to us on Github)"),
0x43, 0x44, 0x2D, 0x43, 0x6F, 0x70, 0x73, 0x2C,
0x20, 0x20, 0x76, 0x65, 0x72, 0x2E, 0x20
}, GetVersion, "CD-Cops (Unconfirmed - Please report to us on Github)"),
// // DVD-Cops, ver.
new(new byte?[]
{
0x44, 0x56, 0x44, 0x2D, 0x43, 0x6F, 0x70, 0x73,
0x2C, 0x20, 0x20, 0x76, 0x65, 0x72, 0x2E, 0x20
}, GetVersion, "DVD-Cops (Unconfirmed - Please report to us on Github)"),
};
// // DVD-Cops, ver.
new(new byte?[]
{
0x44, 0x56, 0x44, 0x2D, 0x43, 0x6F, 0x70, 0x73,
0x2C, 0x20, 0x20, 0x76, 0x65, 0x72, 0x2E, 0x20
}, GetVersion, "DVD-Cops (Unconfirmed - Please report to us on Github)"),
};
return MatchUtil.GetFirstMatch(file, fileContent, contentMatchSets, includeDebug);
}
return null;
return MatchUtil.GetFirstMatch(file, fileContent, contentMatchSets, includeDebug);
}
/// <inheritdoc/>
@@ -120,21 +119,21 @@ namespace BinaryObjectScanner.Protection
if (!string.IsNullOrEmpty(match))
return match;
// Get the resident and non-resident name table strings
var nrntStrs = Array.ConvertAll(nex.Model.NonResidentNameTable ?? [],
nrnte => nrnte?.NameString == null ? string.Empty : Encoding.ASCII.GetString(nrnte.NameString));
// Check the imported-name table
// Found in "h3blade.exe" in Redump entry 85077.
bool importedNameTableEntries = nex.Model.ImportedNameTable?
.Select(kvp => kvp.Value)
bool intMatch = nex.Model.ImportedNameTable?.Values?
.Select(inte => inte?.NameString == null ? string.Empty : Encoding.ASCII.GetString(inte.NameString))
.Any(s => s.Contains("CDCOPS")) ?? false;
if (importedNameTableEntries)
if (intMatch)
return "CD-Cops";
// Check the nonresident-name table
// Found in "CDCOPS.DLL" in Redump entry 85077.
bool nonresidentNameTableEntries = nex.Model.NonResidentNameTable?
.Select(nrnte => nrnte?.NameString == null ? string.Empty : Encoding.ASCII.GetString(nrnte.NameString))
.Any(s => s.Contains("CDcops assembly-language DLL")) ?? false;
if (nonresidentNameTableEntries)
if (Array.Exists(nrntStrs, s => s.Contains("CDcops assembly-language DLL")))
return "CD-Cops";
return null;
@@ -152,14 +151,14 @@ namespace BinaryObjectScanner.Protection
if (pex.StubExecutableData != null)
{
var matchers = new List<ContentMatchSet>
{
// WEBCOPS
// Found in "HyperBowl.C_S" in https://web.archive.org/web/20120616074941/http://icm.games.tucows.com/files2/HyperDemo-109a.exe.
new(new byte?[]
{
0x57, 0x45, 0x42, 0x43, 0x4F, 0x50, 0x53
}, "WEB-Cops")
};
// WEBCOPS
// Found in "HyperBowl.C_S" in https://web.archive.org/web/20120616074941/http://icm.games.tucows.com/files2/HyperDemo-109a.exe.
new(new byte?[]
{
0x57, 0x45, 0x42, 0x43, 0x4F, 0x50, 0x53
}, "WEB-Cops")
};
var match = MatchUtil.GetFirstMatch(file, pex.StubExecutableData, matchers, includeDebug);
if (!string.IsNullOrEmpty(match))
@@ -168,21 +167,19 @@ namespace BinaryObjectScanner.Protection
// Get the .grand section, if it exists
// Found in "AGENTHUG.QZ_" in Redump entry 84517 and "h3blade.QZ_" in Redump entry 85077.
bool grandSection = pex.ContainsSection(".grand", exact: true);
if (grandSection)
if (pex.ContainsSection(".grand", exact: true))
return "CD/DVD/WEB-Cops";
// Get the UNICops section, if it exists
// Found in "FGP.exe" in IA item "flaklypa-grand-prix-dvd"/Redump entry 108169.
bool UNICopsSection = pex.ContainsSection("UNICops", exact: true);
if (UNICopsSection)
if (pex.ContainsSection("UNICops", exact: true))
return "UNI-Cops";
return null;
}
/// <inheritdoc/>
public IEnumerable<string> CheckDirectoryPath(string path, IEnumerable<string>? files)
public List<string> CheckDirectoryPath(string path, List<string>? files)
{
// TODO: Original had "CDCOPS.DLL" required and all the rest in a combined OR
var matchers = new List<PathMatchSet>
@@ -228,14 +225,11 @@ namespace BinaryObjectScanner.Protection
if (fileContent == null)
return null;
byte[] versionBytes = new byte[4];
Array.Copy(fileContent, positions[0] + 15, versionBytes, 0, 4);
char[] version = Array.ConvertAll(versionBytes, b => (char)b);
string version = Encoding.ASCII.GetString(fileContent, positions[0] + 15, 4);
if (version[0] == 0x00)
return string.Empty;
return new string(version);
return version;
}
}
}

View File

@@ -54,7 +54,7 @@ namespace BinaryObjectScanner.Protection
}
/// <inheritdoc/>
public IEnumerable<string> CheckDirectoryPath(string path, IEnumerable<string>? files)
public List<string> CheckDirectoryPath(string path, List<string>? files)
{
var matchers = new List<PathMatchSet>
{

View File

@@ -62,7 +62,7 @@ namespace BinaryObjectScanner.Protection
}
/// <inheritdoc/>
public IEnumerable<string> CheckDirectoryPath(string path, IEnumerable<string>? files)
public List<string> CheckDirectoryPath(string path, List<string>? files)
{
var matchers = new List<PathMatchSet>
{

View File

@@ -17,7 +17,7 @@ namespace BinaryObjectScanner.Protection
public class CDProtector : IPathCheck
{
/// <inheritdoc/>
public IEnumerable<string> CheckDirectoryPath(string path, IEnumerable<string>? files)
public List<string> CheckDirectoryPath(string path, List<string>? files)
{
var matchers = new List<PathMatchSet>
{

View File

@@ -12,7 +12,7 @@ namespace BinaryObjectScanner.Protection
public class CDX : IPathCheck
{
/// <inheritdoc/>
public IEnumerable<string> CheckDirectoryPath(string path, IEnumerable<string>? files)
public List<string> CheckDirectoryPath(string path, List<string>? files)
{
// TODO: Verify if these are OR or AND
var matchers = new List<PathMatchSet>

View File

@@ -10,23 +10,22 @@ namespace BinaryObjectScanner.Protection
/// <inheritdoc/>
public string? CheckContents(string file, byte[] fileContent, bool includeDebug)
{
// Only allow during debug
if (!includeDebug)
return null;
// TODO: Limit these checks to Mac binaries
// TODO: Obtain a sample to find where this string is in a typical executable
if (includeDebug)
var contentMatchSets = new List<ContentMatchSet>
{
var contentMatchSets = new List<ContentMatchSet>
{
// CDSPlayer
new([0x43, 0x44, 0x53, 0x50, 0x6C, 0x61, 0x79, 0x65, 0x72], "Cactus Data Shield 200"),
// CDSPlayer
new([0x43, 0x44, 0x53, 0x50, 0x6C, 0x61, 0x79, 0x65, 0x72], "Cactus Data Shield 200"),
// yucca.cds
new([0x79, 0x75, 0x63, 0x63, 0x61, 0x2E, 0x63, 0x64, 0x73], "Cactus Data Shield 200"),
};
// yucca.cds
new([0x79, 0x75, 0x63, 0x63, 0x61, 0x2E, 0x63, 0x64, 0x73], "Cactus Data Shield 200"),
};
return MatchUtil.GetFirstMatch(file, fileContent, contentMatchSets, includeDebug);
}
return null;
return MatchUtil.GetFirstMatch(file, fileContent, contentMatchSets, includeDebug);
}
}
}

View File

@@ -32,28 +32,22 @@ namespace BinaryObjectScanner.Protection
}
// Get the .cenega section, if it exists. Seems to be found in the protected game executable ("game.exe" in Redump entry 31422 and "Classic Car Racing.exe" in IA item "speed-pack").
bool cenegaSection = pex.ContainsSection(".cenega", exact: true);
if (cenegaSection)
if (pex.ContainsSection(".cenega", exact: true))
return "Cenega ProtectDVD";
// Get the .cenega0 through .cenega2 sections, if they exists. Found in "cenega.dll" in Redump entry 31422 and IA item "speed-pack".
cenegaSection = pex.ContainsSection(".cenega0", exact: true);
if (cenegaSection)
if (pex.ContainsSection(".cenega0", exact: true))
return "Cenega ProtectDVD";
cenegaSection = pex.ContainsSection(".cenega1", exact: true);
if (cenegaSection)
if (pex.ContainsSection(".cenega1", exact: true))
return "Cenega ProtectDVD";
cenegaSection = pex.ContainsSection(".cenega2", exact: true);
if (cenegaSection)
if (pex.ContainsSection(".cenega2", exact: true))
return "Cenega ProtectDVD";
return null;
}
/// <inheritdoc/>
public IEnumerable<string> CheckDirectoryPath(string path, IEnumerable<string>? files)
public List<string> CheckDirectoryPath(string path, List<string>? files)
{
var matchers = new List<PathMatchSet>
{

View File

@@ -61,7 +61,7 @@ namespace BinaryObjectScanner.Protection
}
/// <inheritdoc/>
public IEnumerable<string> CheckDirectoryPath(string path, IEnumerable<string>? files)
public List<string> CheckDirectoryPath(string path, List<string>? files)
{
var matchers = new List<PathMatchSet>
{

View File

@@ -53,7 +53,7 @@ namespace BinaryObjectScanner.Protection
}
/// <inheritdoc/>
public IEnumerable<string> CheckDirectoryPath(string path, IEnumerable<string>? files)
public List<string> CheckDirectoryPath(string path, List<string>? files)
{
var matchers = new List<PathMatchSet>
{

View File

@@ -36,7 +36,7 @@ namespace BinaryObjectScanner.Protection
}
/// <inheritdoc/>
public IEnumerable<string> CheckDirectoryPath(string path, IEnumerable<string>? files)
public List<string> CheckDirectoryPath(string path, List<string>? files)
{
// Previous versions of BOS noted to look at ".PFF" files as possible indicators of CopyKiller, but those files seem unrelated.
// TODO: Figure out why this doesn't work.

View File

@@ -1,7 +1,6 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using BinaryObjectScanner.Interfaces;
using SabreTools.IO.Extensions;
using SabreTools.Matching;
@@ -93,7 +92,7 @@ namespace BinaryObjectScanner.Protection
}
/// <inheritdoc/>
public IEnumerable<string> CheckDirectoryPath(string path, IEnumerable<string>? files)
public List<string> CheckDirectoryPath(string path, List<string>? files)
{
var protections = new List<string>();
if (files == null)
@@ -111,17 +110,17 @@ namespace BinaryObjectScanner.Protection
List<string>? lightFiles = null;
// TODO: Compensate for the check being run a directory or more higher
var fileList = files.Where(f => !f.EndsWith(".x64", StringComparison.OrdinalIgnoreCase));
var fileList = files.FindAll(f => !f.EndsWith(".x64", StringComparison.OrdinalIgnoreCase));
foreach (var dir in dirs)
{
lightFiles = fileList.Where(f =>
lightFiles = fileList.FindAll(f =>
{
f = f.Remove(0, path.Length);
f = f.TrimStart('/', '\\');
return f.StartsWith(dir + Path.DirectorySeparatorChar, StringComparison.OrdinalIgnoreCase);
})
.OrderBy(f => f)
.ToList();
});
lightFiles.Sort();
if (lightFiles.Count > 0)
break;
}
@@ -133,12 +132,12 @@ namespace BinaryObjectScanner.Protection
using var stream = File.OpenRead(lightFiles[0]);
byte[] block = stream.ReadBytes(1024);
// Samples: Redump ID 81628
if (Array.TrueForAll(block, b => b == 0))
protections.Add("copy-X");
var matchers = new List<ContentMatchSet>
{
// Checks if the file contains 0x00
// Samples: Redump ID 81628
new(Enumerable.Repeat<byte?>(0x00, 1024).ToArray(), "copy-X"),
// Checks for whatever this data is.
// Samples: Redump ID 84759, Redump ID 107929. Professional discs also have this data, hence the exclusion check.
new(

View File

@@ -73,7 +73,7 @@ namespace BinaryObjectScanner.Protection
}
/// <inheritdoc/>
public IEnumerable<string> CheckDirectoryPath(string path, IEnumerable<string>? files)
public List<string> CheckDirectoryPath(string path, List<string>? files)
{
var matchers = new List<PathMatchSet>
{

View File

@@ -21,25 +21,22 @@ namespace BinaryObjectScanner.Protection
return null;
// Get the .text section, if it exists
if (pex.ContainsSection(".text"))
var textData = pex.GetFirstSectionData(".text");
if (textData != null)
{
var textData = pex.GetFirstSectionData(".text");
if (textData != null)
var matchers = new List<ContentMatchSet>
{
var matchers = new List<ContentMatchSet>
// Confirmed to detect most examples known of Cucko. The only known exception is the version of "TSLHost.dll" included on Redump entry 36119.
// ŠU‰8...…™...ŠUŠ8T...
new(new byte?[]
{
// Confirmed to detect most examples known of Cucko. The only known exception is the version of "TSLHost.dll" included on Redump entry 36119.
// ŠU‰8...…™...ŠUŠ8T...
new(new byte?[]
{
0x8A, 0x55, 0x89, 0x38, 0x14, 0x1E, 0x0F, 0x85,
0x99, 0x00, 0x00, 0x00, 0x8A, 0x55, 0x8A, 0x38,
0x54, 0x1E, 0x01, 0x0F
}, "Cucko (EA Custom)")
};
0x8A, 0x55, 0x89, 0x38, 0x14, 0x1E, 0x0F, 0x85,
0x99, 0x00, 0x00, 0x00, 0x8A, 0x55, 0x8A, 0x38,
0x54, 0x1E, 0x01, 0x0F
}, "Cucko (EA Custom)")
};
return MatchUtil.GetFirstMatch(file, textData, matchers, includeDebug);
}
return MatchUtil.GetFirstMatch(file, textData, matchers, includeDebug);
}
return null;

View File

@@ -8,7 +8,7 @@ namespace BinaryObjectScanner.Protection
public class DVDCrypt : IPathCheck
{
/// <inheritdoc/>
public IEnumerable<string> CheckDirectoryPath(string path, IEnumerable<string>? files)
public List<string> CheckDirectoryPath(string path, List<string>? files)
{
var matchers = new List<PathMatchSet>
{

View File

@@ -1,6 +1,5 @@
using System.Collections.Generic;
using System.IO;
using System.Linq;
using BinaryObjectScanner.Interfaces;
namespace BinaryObjectScanner.Protection
@@ -9,7 +8,7 @@ namespace BinaryObjectScanner.Protection
public class DVDMoviePROTECT : IPathCheck
{
/// <inheritdoc/>
public IEnumerable<string> CheckDirectoryPath(string path, IEnumerable<string>? files)
public List<string> CheckDirectoryPath(string path, List<string>? files)
{
var protections = new List<string>();
if (files == null)
@@ -17,8 +16,8 @@ namespace BinaryObjectScanner.Protection
if (Directory.Exists(Path.Combine(path, "VIDEO_TS")))
{
string[] bupfiles = files.Where(s => s.EndsWith(".bup")).ToArray();
for (int i = 0; i < bupfiles.Length; i++)
var bupfiles = files.FindAll(s => s.EndsWith(".bup"));
for (int i = 0; i < bupfiles.Count; i++)
{
var bupfile = new FileInfo(bupfiles[i]);
if (bupfile.DirectoryName == null)

View File

@@ -5,6 +5,7 @@ using SabreTools.Matching;
using SabreTools.Matching.Content;
using SabreTools.Matching.Paths;
using SabreTools.Serialization.Wrappers;
using OHMN = SabreTools.Models.PortableExecutable.OptionalHeaderMagicNumber;
namespace BinaryObjectScanner.Protection
{
@@ -65,205 +66,207 @@ namespace BinaryObjectScanner.Protection
// https://github.com/horsicq/Detect-It-Easy/blob/master/db/PE/Denuvo%20protector.2.sg
// https://github.com/horsicq/Detect-It-Easy/blob/master/db/PE/_denuvoComplete.2.sg
// TODO: Re-enable all Entry Point checks after implementing
// Denuvo Protector
// if (pex.OptionalHeader.Magic == OptionalHeaderType.PE32Plus && pex.EntryPointRaw != null)
// {
// byte?[] denuvoProtector = new byte?[]
// {
// 0x48, 0x8D, 0x0D, null, null, null, null, null,
// null, null, null, 0xE9, null, null, null, null,
// 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
// };
if (pex.Model.OptionalHeader?.Magic == OHMN.PE32Plus
&& pex.EntryPointData != null)
{
byte?[] denuvoProtector =
[
0x48, 0x8D, 0x0D, null, null, null, null, null,
null, null, null, 0xE9, null, null, null, null,
0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
];
// if (pex.EntryPointRaw.StartsWith(denuvoProtector))
// return "Denuvo Protector";
// }
if (pex.EntryPointData.StartsWith(denuvoProtector))
return "Denuvo Protector";
}
// Denuvo
var timingMatchers = new List<ContentMatchSet>
{
// Denuvo Timing
new(
new byte?[]
{
[
0x44, 0x65, 0x6E, 0x75, 0x76, 0x6F, 0x20, 0x54,
0x69, 0x6D, 0x69, 0x6E, 0x67,
}, "Denuvo")
], "Denuvo")
};
var timingMatch = MatchUtil.GetFirstMatch(file, pex.EntryPointData, timingMatchers, includeDebug);
// TODO: Re-enable all Entry Point checks after implementing
// if (pex.ContainsSection(".arch") || pex.ContainsSection(".srdata") || !string.IsNullOrEmpty(MatchUtil.GetFirstMatch(file, pex.EntryPointRaw, timingMatchers, includeDebug)))
// {
// if (pex.OH_Magic == OptionalHeaderType.PE32Plus)
// {
// var matchers = new List<ContentMatchSet>
// {
// // Mad Max, Metal Gear Solid: TPP, Rise of the Tomb Raider
// new ContentMatchSet(
// new ContentMatch(
// new byte?[]
// {
// 0x51, 0x52, 0x41, 0x50, 0x41, 0x51, 0x4C, 0x8D,
// null, null, null, null, null, 0x4C, 0x8D, null,
// null, null, null, null, 0x4D, 0x29, 0xC1,
// },
// end: 0
// ),
// "Denuvo v1.0 (x64)"),
if (pex.ContainsSection(".arch")
|| pex.ContainsSection(".srdata")
|| !string.IsNullOrEmpty(timingMatch))
{
if (pex.Model.OptionalHeader?.Magic == OHMN.PE32Plus)
{
var matchers = new List<ContentMatchSet>
{
// Mad Max, Metal Gear Solid: TPP, Rise of the Tomb Raider
new(
new ContentMatch(
new byte?[]
{
0x51, 0x52, 0x41, 0x50, 0x41, 0x51, 0x4C, 0x8D,
null, null, null, null, null, 0x4C, 0x8D, null,
null, null, null, null, 0x4D, 0x29, 0xC1,
},
end: 0
),
"Denuvo v1.0 (x64)"),
// // Lords of the Fallen, Batman: AK, Just Cause 3, Sherlock Holmes: TdD, Tales of Berseria etc
// new ContentMatchSet(
// new ContentMatch(
// new byte?[]
// {
// 0x48, 0x8D, 0x0D, null, null, null, null, 0xE9,
// null, null, null, null,
// },
// end: 0
// ),
// "Denuvo v2.0a (x64)"),
// Lords of the Fallen, Batman: AK, Just Cause 3, Sherlock Holmes: TdD, Tales of Berseria etc
new(
new ContentMatch(
new byte?[]
{
0x48, 0x8D, 0x0D, null, null, null, null, 0xE9,
null, null, null, null,
},
end: 0
),
"Denuvo v2.0a (x64)"),
// // Yesterday Origins
// new ContentMatchSet(
// new ContentMatch(
// new byte?[]
// {
// 0x48, 0x89, null, null, null, null, null, 0x48,
// 0x89, null, null, null, null, null, 0x4C, 0x89,
// null, null, null, null, null, 0x4C, 0x89, null,
// null, null, null, null, 0x48, 0x83, 0xFA, 0x01,
// },
// end: 0
// ),
// "Denuvo v2.0b (x64)"),
// Yesterday Origins
new(
new ContentMatch(
new byte?[]
{
0x48, 0x89, null, null, null, null, null, 0x48,
0x89, null, null, null, null, null, 0x4C, 0x89,
null, null, null, null, null, 0x4C, 0x89, null,
null, null, null, null, 0x48, 0x83, 0xFA, 0x01,
},
end: 0
),
"Denuvo v2.0b (x64)"),
// // Sniper Ghost Warrior 3 (beta), Dead Rising 4 (SteamStub-free)
// new ContentMatchSet(
// new ContentMatch(
// new byte?[]
// {
// null, null, null, null, null, null, null, null,
// 0x4C, 0x89, 0x1C, 0x24, 0x49, 0x89, 0xE3,
// },
// end: 0
// ),
// "Denuvo v3.0a (x64)"),
// Sniper Ghost Warrior 3 (beta), Dead Rising 4 (SteamStub-free)
new(
new ContentMatch(
new byte?[]
{
null, null, null, null, null, null, null, null,
0x4C, 0x89, 0x1C, 0x24, 0x49, 0x89, 0xE3,
},
end: 0
),
"Denuvo v3.0a (x64)"),
// // Train Sim World CSX Heavy Haul
// new ContentMatchSet(
// new ContentMatch(
// new byte?[]
// {
// 0x4D, 0x8D, null, null, null, null, null, null,
// null, null, null, 0x48, 0x89, null, null, null,
// null, null, 0x48, 0x8D, null, null, 0x48, 0x89,
// null, 0x48, 0x89, null, 0x48, 0x89,
// },
// end: 0
// ),
// "Denuvo v3.0b (x64)"),
// };
// Train Sim World CSX Heavy Haul
new(
new ContentMatch(
new byte?[]
{
0x4D, 0x8D, null, null, null, null, null, null,
null, null, null, 0x48, 0x89, null, null, null,
null, null, 0x48, 0x8D, null, null, 0x48, 0x89,
null, 0x48, 0x89, null, 0x48, 0x89,
},
end: 0
),
"Denuvo v3.0b (x64)"),
};
// var match = MatchUtil.GetFirstMatch(file, pex.EntryPointRaw, matchers, includeDebug);
// if (!string.IsNullOrEmpty(match))
// return match;
var match = MatchUtil.GetFirstMatch(file, pex.EntryPointData, matchers, includeDebug);
if (!string.IsNullOrEmpty(match))
return match;
// return "Denuvo (Unknown x64 Version)";
return "Denuvo (Unknown x64 Version)";
// //// Check if steam_api64.dll present
// //if (PE.isLibraryPresent("steam_api64.dll"))
// //{
// // // Override additional info
// // sOptions = "x64 -> Steam";
// // bDetected = 1;
// //}
// //// Check if uplay_r1_loader64.dll present
// //if (PE.isLibraryPresent("uplay_r1_loader64.dll"))
// //{
// // // Override additional info
// // sOptions = "x64 -> uPlay";
// // bDetected = 1;
// //}
// //// Check if uplay_r2_loader64.dll present
// //if (PE.isLibraryPresent("uplay_r2_loader64.dll"))
// //{
// // // Override additional info
// // sOptions = "x64 -> uPlay";
// // bDetected = 1;
// //}
// //// Check if Core/Activation64.dll present
// //if (PE.isLibraryPresent("Core/Activation64.dll"))
// //{
// // // Override additional info
// // sOptions = "x64 -> Origin";
// // bDetected = 1;
// //}
// }
// else
// {
// var matchers = new List<ContentMatchSet>
// {
// // Pro Evolution Soccer 2017, Champions of Anteria
// new ContentMatchSet(
// new ContentMatch(
// new byte?[]
// {
// 0x55, 0x89, 0xE5, 0x8D, null, null, null, null,
// null, null, 0xE8, null, null, null, null, 0xE8,
// null, null, null, null, 0xE8, null, null, null,
// null, 0xE8, null, null, null, null,
// },
// end: 0
// ),
// "Denuvo v1.0 (x86)"),
//// Check if steam_api64.dll present
//if (PE.isLibraryPresent("steam_api64.dll"))
//{
// // Override additional info
// sOptions = "x64 -> Steam";
// bDetected = 1;
//}
//// Check if uplay_r1_loader64.dll present
//if (PE.isLibraryPresent("uplay_r1_loader64.dll"))
//{
// // Override additional info
// sOptions = "x64 -> uPlay";
// bDetected = 1;
//}
//// Check if uplay_r2_loader64.dll present
//if (PE.isLibraryPresent("uplay_r2_loader64.dll"))
//{
// // Override additional info
// sOptions = "x64 -> uPlay";
// bDetected = 1;
//}
//// Check if Core/Activation64.dll present
//if (PE.isLibraryPresent("Core/Activation64.dll"))
//{
// // Override additional info
// sOptions = "x64 -> Origin";
// bDetected = 1;
//}
}
else
{
var matchers = new List<ContentMatchSet>
{
// Pro Evolution Soccer 2017, Champions of Anteria
new(
new ContentMatch(
new byte?[]
{
0x55, 0x89, 0xE5, 0x8D, null, null, null, null,
null, null, 0xE8, null, null, null, null, 0xE8,
null, null, null, null, 0xE8, null, null, null,
null, 0xE8, null, null, null, null,
},
end: 0
),
"Denuvo v1.0 (x86)"),
// // Romance of 13 Kingdoms, 2Dark
// new ContentMatchSet(
// new ContentMatch(
// new byte?[]
// {
// 0x8D, null, null, null, null, null, null, 0x89,
// 0x7C, 0x24, 0x04, 0x89, 0xE7,
// },
// end: 0
// ),
// "Denuvo v2.0 (x86)"),
// };
// Romance of 13 Kingdoms, 2Dark
new(
new ContentMatch(
new byte?[]
{
0x8D, null, null, null, null, null, null, 0x89,
0x7C, 0x24, 0x04, 0x89, 0xE7,
},
end: 0
),
"Denuvo v2.0 (x86)"),
};
// var match = MatchUtil.GetFirstMatch(file, pex.EntryPointRaw, matchers, includeDebug);
// if (!string.IsNullOrEmpty(match))
// return match;
var match = MatchUtil.GetFirstMatch(file, pex.EntryPointData, matchers, includeDebug);
if (!string.IsNullOrEmpty(match))
return match;
// //// Check if steam_api64.dll present
// //if (PE.isLibraryPresent("steam_api.dll"))
// //{
// // // Override additional info
// // sOptions = "x86 -> Steam";
// // bDetected = 1;
// //}
// //// Check if uplay_r1_loader.dll present
// //if (PE.isLibraryPresent("uplay_r1_loader.dll"))
// //{
// // // Override additional info
// // sOptions = "x86 -> uPlay";
// // bDetected = 1;
// //}
// //// Check if Core/Activation.dll present
// //if (PE.isLibraryPresent("Core/Activation.dll"))
// //{
// // // Override additional info
// // sOptions = "x86 -> Origin";
// // bDetected = 1;
// //}
// }
// }
//// Check if steam_api64.dll present
//if (PE.isLibraryPresent("steam_api.dll"))
//{
// // Override additional info
// sOptions = "x86 -> Steam";
// bDetected = 1;
//}
//// Check if uplay_r1_loader.dll present
//if (PE.isLibraryPresent("uplay_r1_loader.dll"))
//{
// // Override additional info
// sOptions = "x86 -> uPlay";
// bDetected = 1;
//}
//// Check if Core/Activation.dll present
//if (PE.isLibraryPresent("Core/Activation.dll"))
//{
// // Override additional info
// sOptions = "x86 -> Origin";
// bDetected = 1;
//}
}
}
return null;
}
/// <inheritdoc/>
public IEnumerable<string> CheckDirectoryPath(string path, IEnumerable<string>? files)
public List<string> CheckDirectoryPath(string path, List<string>? files)
{
var matchers = new List<PathMatchSet>
{

View File

@@ -52,7 +52,7 @@ namespace BinaryObjectScanner.Protection
}
/// <inheritdoc/>
public IEnumerable<string> CheckDirectoryPath(string path, IEnumerable<string>? files)
public List<string> CheckDirectoryPath(string path, List<string>? files)
{
var matchers = new List<PathMatchSet>
{

View File

@@ -22,7 +22,7 @@ namespace BinaryObjectScanner.Protection
// https://www.gamecopyworld.com/games/pc_pc_calcio_2000.shtml
// https://www.gamecopyworld.com/games/pc_pc_futbol_2000.shtml
public IEnumerable<string> CheckDirectoryPath(string path, IEnumerable<string>? files)
public List<string> CheckDirectoryPath(string path, List<string>? files)
{
var matchers = new List<PathMatchSet>
{

View File

@@ -1,7 +1,6 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using BinaryObjectScanner.Interfaces;
using SabreTools.Matching;
using SabreTools.Matching.Content;
@@ -66,79 +65,79 @@ namespace BinaryObjectScanner.Protection
return "DiscGuard";
// Found in "Alternate.exe" (Redump entry 31914) and "Alt.exe" (Redump entries 46743, 46961, 79284, and 79374).
var resources = pex.FindStringTableByEntry("DiscGuard")
.Concat(pex.FindStringTableByEntry("The file Dg.vbn was not found."))
.Concat(pex.FindStringTableByEntry("The file IosLink.VxD was not found."))
.Concat(pex.FindStringTableByEntry("The file IosLink.sys was not found."));
if (resources.Any())
List<Dictionary<int, string?>?> resources =
[
.. pex.FindStringTableByEntry("DiscGuard"),
.. pex.FindStringTableByEntry("The file Dg.vbn was not found."),
.. pex.FindStringTableByEntry("The file IosLink.VxD was not found."),
.. pex.FindStringTableByEntry("The file IosLink.sys was not found."),
];
if (resources.Count > 0)
return "DiscGuard";
// Get the .vbn section, if it exists
if (pex.ContainsSection(".vbn"))
var vbnData = pex.GetFirstSectionData(".vbn");
if (vbnData != null)
{
var vbnData = pex.GetFirstSectionData(".vbn");
if (vbnData != null)
var matchers = new List<ContentMatchSet>
{
var matchers = new List<ContentMatchSet>
// Found in "T29.dll" (Redump entry 31914).
// This check should be as long as the following check, as this data is nearly identical (including length) in the original files, but for some reason the section ends early, causing part of the remaining data to not be part of a section.
new(new byte?[]
{
// Found in "T29.dll" (Redump entry 31914).
// This check should be as long as the following check, as this data is nearly identical (including length) in the original files, but for some reason the section ends early, causing part of the remaining data to not be part of a section.
new(new byte?[]
{
0x7B, 0x39, 0x8F, 0x07, 0x47, 0xE9, 0x96, 0x8C, 0xCA, 0xB2, 0x5C, 0x50,
0xC7, 0x5A, 0x18, 0xBD, 0x75, 0xB5, 0x68, 0x6A, 0x78, 0xB5, 0xCF, 0xF2,
0xBE, 0xB3, 0xDB, 0xE9, 0x4E, 0x87, 0x8D, 0x46, 0x63, 0x0A, 0x54, 0xB8,
0x4F, 0x85, 0x60, 0x2C, 0x06, 0xEC, 0xBD, 0x75, 0xF5, 0x6A, 0x6E, 0x35,
0x4D, 0x5A, 0x8B, 0xF4, 0x12, 0x15, 0x23, 0xC8, 0xE9, 0x80, 0x01, 0x10,
0xFE, 0xDB, 0xC6, 0x70, 0x1D, 0xC1, 0x4D, 0xAE, 0x9E, 0xE1, 0x01, 0xAA,
0x9E, 0x50, 0x50, 0xC5, 0x66, 0x80, 0xC0, 0xA2, 0x2F, 0xA9, 0x7A, 0x3B,
0x48, 0x74, 0x9D, 0x17, 0x33, 0x5D, 0x4C, 0x84, 0xD9, 0x54, 0xC4, 0x08,
0xCC, 0x10, 0x2A, 0xF6, 0x91, 0x40, 0x51, 0xD3, 0xF5, 0x9A, 0x07, 0xE7,
0xAB, 0xE9, 0x0B, 0xAD, 0xD4, 0x3A, 0xEC, 0xBA, 0x4B, 0x6C, 0xD2, 0x82,
0x0D, 0xF5, 0x49, 0x83, 0x8E, 0xAB, 0x85, 0x92, 0x78, 0x1D, 0x69, 0x1E,
0x44, 0xC6, 0xF6, 0xB4, 0x5F, 0x5F, 0xC2, 0x48, 0x5A, 0xED, 0x43, 0xD3,
0xA4, 0x41, 0x81
}, GetVersion, "DiscGuard"),
0x7B, 0x39, 0x8F, 0x07, 0x47, 0xE9, 0x96, 0x8C, 0xCA, 0xB2, 0x5C, 0x50,
0xC7, 0x5A, 0x18, 0xBD, 0x75, 0xB5, 0x68, 0x6A, 0x78, 0xB5, 0xCF, 0xF2,
0xBE, 0xB3, 0xDB, 0xE9, 0x4E, 0x87, 0x8D, 0x46, 0x63, 0x0A, 0x54, 0xB8,
0x4F, 0x85, 0x60, 0x2C, 0x06, 0xEC, 0xBD, 0x75, 0xF5, 0x6A, 0x6E, 0x35,
0x4D, 0x5A, 0x8B, 0xF4, 0x12, 0x15, 0x23, 0xC8, 0xE9, 0x80, 0x01, 0x10,
0xFE, 0xDB, 0xC6, 0x70, 0x1D, 0xC1, 0x4D, 0xAE, 0x9E, 0xE1, 0x01, 0xAA,
0x9E, 0x50, 0x50, 0xC5, 0x66, 0x80, 0xC0, 0xA2, 0x2F, 0xA9, 0x7A, 0x3B,
0x48, 0x74, 0x9D, 0x17, 0x33, 0x5D, 0x4C, 0x84, 0xD9, 0x54, 0xC4, 0x08,
0xCC, 0x10, 0x2A, 0xF6, 0x91, 0x40, 0x51, 0xD3, 0xF5, 0x9A, 0x07, 0xE7,
0xAB, 0xE9, 0x0B, 0xAD, 0xD4, 0x3A, 0xEC, 0xBA, 0x4B, 0x6C, 0xD2, 0x82,
0x0D, 0xF5, 0x49, 0x83, 0x8E, 0xAB, 0x85, 0x92, 0x78, 0x1D, 0x69, 0x1E,
0x44, 0xC6, 0xF6, 0xB4, 0x5F, 0x5F, 0xC2, 0x48, 0x5A, 0xED, 0x43, 0xD3,
0xA4, 0x41, 0x81
}, GetVersion, "DiscGuard"),
// Found in "T5375.dll" (Redump entry 79284), "TD352.dll" and "TE091.dll" (Redump entry 46743), "T71E1.dll" and "T7181.dll" (Redump entry 46961), and "TA0E4.DLL" (Redump entry 79374).
new(new byte?[]
{
0x7B, 0x39, 0x8F, 0x07, 0x45, 0xE9, 0x96, 0x8C, 0xCA, 0xB2, 0x5C, 0x50,
0xC7, 0x5A, 0x18, 0xBD, 0x75, 0xB5, 0x68, 0x6A, 0x78, 0xB5, 0xCF, 0xF2,
0xBE, 0xB3, 0xDB, 0xE9, 0x4E, 0x87, 0x8D, 0x46, 0x63, 0x0A, 0x54, 0xB8,
0x4F, 0x85, 0x60, 0x2C, 0x06, 0xEC, 0xBD, 0x75, 0xC6, 0xEB, 0x6E, 0x35,
0xED, 0xD0, 0x8B, 0xF4, 0x15, 0x12, 0x3D, 0xF3, 0x65, 0xF7, 0x01, 0x10,
0xF8, 0xFA, 0xC6, 0x70, 0x1D, 0xC1, 0x4D, 0xAE, 0x9E, 0xE1, 0x01, 0xAA,
0x9E, 0x50, 0x50, 0xC5, 0x66, 0x80, 0xC0, 0xA2, 0x2F, 0xA9, 0x7A, 0x3B,
0x48, 0x74, 0x9D, 0x17, 0x33, 0x5D, 0x4C, 0x84, 0xD9, 0x54, 0xC4, 0x08,
0xCC, 0x10, 0x2A, 0xF6, 0x91, 0x40, 0x51, 0xD3, 0x41, 0x9A, 0x07, 0xE7,
0xAB, 0xE9, 0x0B, 0xAD, 0xD4, 0x3A, 0xEC, 0xBA, 0xAF, 0x69, 0xD2, 0x82,
0x67, 0xF5, 0x49, 0x83, 0x8E, 0xAB, 0x85, 0x92, 0x04, 0x19, 0x69, 0x1E,
0x44, 0xC6, 0xF6, 0xB4, 0x5F, 0x5F, 0xC2, 0x48, 0x5A, 0xED, 0x43, 0xD3,
0xA4, 0x41, 0x81, 0xAF, 0xB8, 0xCB, 0x46, 0xE3, 0xDA, 0x05, 0x36, 0xEA,
0x05, 0xF5, 0xB9, 0xCE, 0x5F, 0x9A, 0xF5, 0x7D, 0x9E, 0x64, 0x66, 0xF9,
0xA5, 0x7C, 0x4D, 0x1D, 0x1D, 0x95, 0x02, 0x52, 0x66, 0x23, 0xEF, 0xFF,
0xEC, 0x63, 0x11, 0xEB, 0xF6, 0x66, 0x8F, 0x2B, 0xCF, 0x07, 0x50, 0x18,
0xBE, 0x58, 0xCA, 0x08, 0x24, 0xAD, 0x81, 0x1A, 0xAB, 0x0E, 0x2D, 0x16,
0x38, 0xAB, 0x22, 0xB5, 0xA8, 0xF0, 0x7D, 0x2E, 0xAF, 0x5E, 0xEA, 0x02,
0x72, 0x20, 0x14, 0x19, 0x0E, 0x31, 0xF3, 0xD0, 0x40, 0xAE, 0xA2, 0xD5,
0x0A, 0xA7, 0xB7, 0xAE, 0x02, 0xCF, 0xAC, 0x5F, 0xB8, 0x03, 0x15, 0x80,
0x9A, 0x58, 0x5C, 0x03, 0x28, 0x31, 0x9E, 0xB8, 0x21, 0x5D, 0x07, 0xB3,
0xB9, 0xEC, 0x75, 0xBA, 0xC2, 0xC8, 0x9D, 0x6F, 0x7A, 0xA1, 0x00, 0x8A
}, GetVersion, "DiscGuard"),
};
// Found in "T5375.dll" (Redump entry 79284), "TD352.dll" and "TE091.dll" (Redump entry 46743), "T71E1.dll" and "T7181.dll" (Redump entry 46961), and "TA0E4.DLL" (Redump entry 79374).
new(new byte?[]
{
0x7B, 0x39, 0x8F, 0x07, 0x45, 0xE9, 0x96, 0x8C, 0xCA, 0xB2, 0x5C, 0x50,
0xC7, 0x5A, 0x18, 0xBD, 0x75, 0xB5, 0x68, 0x6A, 0x78, 0xB5, 0xCF, 0xF2,
0xBE, 0xB3, 0xDB, 0xE9, 0x4E, 0x87, 0x8D, 0x46, 0x63, 0x0A, 0x54, 0xB8,
0x4F, 0x85, 0x60, 0x2C, 0x06, 0xEC, 0xBD, 0x75, 0xC6, 0xEB, 0x6E, 0x35,
0xED, 0xD0, 0x8B, 0xF4, 0x15, 0x12, 0x3D, 0xF3, 0x65, 0xF7, 0x01, 0x10,
0xF8, 0xFA, 0xC6, 0x70, 0x1D, 0xC1, 0x4D, 0xAE, 0x9E, 0xE1, 0x01, 0xAA,
0x9E, 0x50, 0x50, 0xC5, 0x66, 0x80, 0xC0, 0xA2, 0x2F, 0xA9, 0x7A, 0x3B,
0x48, 0x74, 0x9D, 0x17, 0x33, 0x5D, 0x4C, 0x84, 0xD9, 0x54, 0xC4, 0x08,
0xCC, 0x10, 0x2A, 0xF6, 0x91, 0x40, 0x51, 0xD3, 0x41, 0x9A, 0x07, 0xE7,
0xAB, 0xE9, 0x0B, 0xAD, 0xD4, 0x3A, 0xEC, 0xBA, 0xAF, 0x69, 0xD2, 0x82,
0x67, 0xF5, 0x49, 0x83, 0x8E, 0xAB, 0x85, 0x92, 0x04, 0x19, 0x69, 0x1E,
0x44, 0xC6, 0xF6, 0xB4, 0x5F, 0x5F, 0xC2, 0x48, 0x5A, 0xED, 0x43, 0xD3,
0xA4, 0x41, 0x81, 0xAF, 0xB8, 0xCB, 0x46, 0xE3, 0xDA, 0x05, 0x36, 0xEA,
0x05, 0xF5, 0xB9, 0xCE, 0x5F, 0x9A, 0xF5, 0x7D, 0x9E, 0x64, 0x66, 0xF9,
0xA5, 0x7C, 0x4D, 0x1D, 0x1D, 0x95, 0x02, 0x52, 0x66, 0x23, 0xEF, 0xFF,
0xEC, 0x63, 0x11, 0xEB, 0xF6, 0x66, 0x8F, 0x2B, 0xCF, 0x07, 0x50, 0x18,
0xBE, 0x58, 0xCA, 0x08, 0x24, 0xAD, 0x81, 0x1A, 0xAB, 0x0E, 0x2D, 0x16,
0x38, 0xAB, 0x22, 0xB5, 0xA8, 0xF0, 0x7D, 0x2E, 0xAF, 0x5E, 0xEA, 0x02,
0x72, 0x20, 0x14, 0x19, 0x0E, 0x31, 0xF3, 0xD0, 0x40, 0xAE, 0xA2, 0xD5,
0x0A, 0xA7, 0xB7, 0xAE, 0x02, 0xCF, 0xAC, 0x5F, 0xB8, 0x03, 0x15, 0x80,
0x9A, 0x58, 0x5C, 0x03, 0x28, 0x31, 0x9E, 0xB8, 0x21, 0x5D, 0x07, 0xB3,
0xB9, 0xEC, 0x75, 0xBA, 0xC2, 0xC8, 0x9D, 0x6F, 0x7A, 0xA1, 0x00, 0x8A
}, GetVersion, "DiscGuard"),
};
var match = MatchUtil.GetFirstMatch(file, vbnData, matchers, includeDebug);
if (!string.IsNullOrEmpty(match))
return match;
}
var match = MatchUtil.GetFirstMatch(file, vbnData, matchers, includeDebug);
if (!string.IsNullOrEmpty(match))
return match;
}
return null;
}
/// <inheritdoc/>
public IEnumerable<string> CheckDirectoryPath(string path, IEnumerable<string>? files)
public List<string> CheckDirectoryPath(string path, List<string>? files)
{
var matchers = new List<PathMatchSet>
{

View File

@@ -46,7 +46,7 @@ namespace BinaryObjectScanner.Protection
}
/// <inheritdoc/>
public IEnumerable<string> CheckDirectoryPath(string path, IEnumerable<string>? files)
public List<string> CheckDirectoryPath(string path, List<string>? files)
{
var matchers = new List<PathMatchSet>
{

View File

@@ -80,7 +80,7 @@ namespace BinaryObjectScanner.Protection
}
/// <inheritdoc/>
public IEnumerable<string> CheckDirectoryPath(string path, IEnumerable<string>? files)
public List<string> CheckDirectoryPath(string path, List<string>? files)
{
// TODO: Search for the presence of the folder "EasyAntiCheat" specifically, which is present in every checked version so far.
var matchers = new List<PathMatchSet>

View File

@@ -1,5 +1,4 @@
using System;
using System.Linq;
using BinaryObjectScanner.Interfaces;
using SabreTools.Serialization.Wrappers;
@@ -27,9 +26,9 @@ namespace BinaryObjectScanner.Protection
if (name?.Equals("CDCode", StringComparison.Ordinal) == true)
return $"EA CdKey Registration Module {pex.GetInternalVersion()}";
if (pex.FindDialogByTitle("About CDKey").Any())
if (pex.FindDialogByTitle("About CDKey").Count > 0)
return $"EA CdKey Registration Module {pex.GetInternalVersion()}";
else if (pex.FindGenericResource("About CDKey").Any())
else if (pex.FindGenericResource("About CDKey").Count > 0)
return $"EA CdKey Registration Module {pex.GetInternalVersion()}";
// Get the .data/DATA section strings, if they exist

View File

@@ -27,11 +27,12 @@ namespace BinaryObjectScanner.Protection
// Detects Engine32 within the game executables that contain it.
if (pex.Model.ImportTable?.ImportDirectoryTable != null && pex.Model.ImportTable?.HintNameTable != null)
{
bool importDirectoryTableMatch = Array.Exists(pex.Model.ImportTable.ImportDirectoryTable, idte => idte?.Name != null && idte.Name.Equals("ENGINE32.DLL", StringComparison.OrdinalIgnoreCase));
bool hintNameTableMatch = Array.Exists(pex.Model.ImportTable?.HintNameTable ?? [], ihne => ihne?.Name == "InitEngine");
bool importDirectoryTableMatch = Array.Exists(pex.Model.ImportTable.ImportDirectoryTable,
idte => idte?.Name != null && idte.Name.Equals("ENGINE32.DLL", StringComparison.OrdinalIgnoreCase));
bool hintNameTableMatch = Array.Exists(pex.Model.ImportTable.HintNameTable,
ihne => ihne?.Name == "InitEngine");
// The Hint/Name Table Entry "DeinitEngine" is present in every tested sample, aside from TOCA Race Driver 2 (Redump entries 104593-104596).
if (hintNameTableMatch && importDirectoryTableMatch)
return "Engine32";
}
@@ -50,7 +51,7 @@ namespace BinaryObjectScanner.Protection
}
/// <inheritdoc/>
public IEnumerable<string> CheckDirectoryPath(string path, IEnumerable<string>? files)
public List<string> CheckDirectoryPath(string path, List<string>? files)
{
var matchers = new List<PathMatchSet>
{

View File

@@ -15,7 +15,7 @@ namespace BinaryObjectScanner.Protection
// TODO: Add an MS-DOS executable check for "FREELOCK.EXE".
/// <inheritdoc/>
public IEnumerable<string> CheckDirectoryPath(string path, IEnumerable<string>? files)
public List<string> CheckDirectoryPath(string path, List<string>? files)
{
var matchers = new List<PathMatchSet>
{

View File

@@ -34,7 +34,7 @@ namespace BinaryObjectScanner.Protection
}
/// <inheritdoc/>
public IEnumerable<string> CheckDirectoryPath(string path, IEnumerable<string>? files)
public List<string> CheckDirectoryPath(string path, List<string>? files)
{
var matchers = new List<PathMatchSet>
{

View File

@@ -38,7 +38,7 @@ namespace BinaryObjectScanner.Protection
}
/// <inheritdoc/>
public IEnumerable<string> CheckDirectoryPath(string path, IEnumerable<string>? files)
public List<string> CheckDirectoryPath(string path, List<string>? files)
{
var matchers = new List<PathMatchSet>
{

View File

@@ -67,7 +67,7 @@ namespace BinaryObjectScanner.Protection
}
/// <inheritdoc/>
public IEnumerable<string> CheckDirectoryPath(string path, IEnumerable<string>? files)
public List<string> CheckDirectoryPath(string path, List<string>? files)
{
var matchers = new List<PathMatchSet>
{

View File

@@ -33,10 +33,12 @@ namespace BinaryObjectScanner.Protection
return $"Stardock Product Activation {pex.GetInternalVersion()}";
// TODO: Check for CVP* instead?
bool containsCheck = Array.Exists(pex.Model.ExportTable?.ExportNameTable?.Strings ?? [], s => s?.StartsWith("CVPInitializeClient") ?? false);
bool containsCheck2 = false;
bool containsCheck = false;
if (pex.Model.ExportTable?.ExportNameTable?.Strings != null)
containsCheck = Array.Exists(pex.Model.ExportTable.ExportNameTable.Strings, s => s?.StartsWith("CVPInitializeClient") ?? false);
// Get the .rdata section strings, if they exist
bool containsCheck2 = false;
var strs = pex.GetFirstSectionStrings(".rdata");
if (strs != null)
{
@@ -54,7 +56,7 @@ namespace BinaryObjectScanner.Protection
}
/// <inheritdoc/>
public IEnumerable<string> CheckDirectoryPath(string path, IEnumerable<string>? files)
public List<string> CheckDirectoryPath(string path, List<string>? files)
{
var matchers = new List<PathMatchSet>
{

View File

@@ -12,7 +12,7 @@ namespace BinaryObjectScanner.Protection
public class IndyVCD : IPathCheck
{
/// <inheritdoc/>
public IEnumerable<string> CheckDirectoryPath(string path, IEnumerable<string>? files)
public List<string> CheckDirectoryPath(string path, List<string>? files)
{
// TODO: Verify if these are OR or AND
var matchers = new List<PathMatchSet>

View File

@@ -1,5 +1,4 @@
using System.Linq;
using BinaryObjectScanner.Interfaces;
using BinaryObjectScanner.Interfaces;
using SabreTools.Serialization.Wrappers;
namespace BinaryObjectScanner.Protection
@@ -30,8 +29,7 @@ namespace BinaryObjectScanner.Protection
if (sections == null)
return null;
var fileNameResource = pex.FindGenericResource("NO NESTED PRMS SUPPORTED");
if (fileNameResource.Any())
if (pex.FindGenericResource("NO NESTED PRMS SUPPORTED").Count > 0)
return "INTENIUM Trial & Buy Protection";
return null;

View File

@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using System.Text;
using BinaryObjectScanner.Interfaces;
using SabreTools.Matching;
using SabreTools.Matching.Content;
@@ -72,12 +73,7 @@ namespace BinaryObjectScanner.Protection
if (fileContent == null)
return null;
int position = positions[0];
byte[] versionBytes = new byte[8];
Array.Copy(fileContent, position + 67, versionBytes, 0, 8);
char[] version = Array.ConvertAll(versionBytes, b => (char)b);
return new string(version);
return Encoding.ASCII.GetString(fileContent, positions[0] + 67, 8);
}
}
}

View File

@@ -56,7 +56,7 @@ namespace BinaryObjectScanner.Protection
}
/// <inheritdoc/>
public IEnumerable<string> CheckDirectoryPath(string path, IEnumerable<string>? files)
public List<string> CheckDirectoryPath(string path, List<string>? files)
{
var matchers = new List<PathMatchSet>
{

View File

@@ -10,23 +10,22 @@ namespace BinaryObjectScanner.Protection
/// <inheritdoc/>
public string? CheckContents(string file, byte[] fileContent, bool includeDebug)
{
// Only allow during debug
if (!includeDebug)
return null;
// TODO: Obtain a sample to find where this string is in a typical executable
if (includeDebug)
var contentMatchSets = new List<ContentMatchSet>
{
var contentMatchSets = new List<ContentMatchSet>
// KEY-LOCK COMMAND
new(new byte?[]
{
// KEY-LOCK COMMAND
new(new byte?[]
{
0x4B, 0x45, 0x59, 0x2D, 0x4C, 0x4F, 0x43, 0x4B,
0x20, 0x43, 0x4F, 0x4D, 0x4D, 0x41, 0x4E, 0x44
}, "Key-Lock (Dongle) (Unconfirmed - Please report to us on Github)"),
};
0x4B, 0x45, 0x59, 0x2D, 0x4C, 0x4F, 0x43, 0x4B,
0x20, 0x43, 0x4F, 0x4D, 0x4D, 0x41, 0x4E, 0x44
}, "Key-Lock (Dongle) (Unconfirmed - Please report to us on Github)"),
};
return MatchUtil.GetFirstMatch(file, fileContent, contentMatchSets, includeDebug);
}
return null;
return MatchUtil.GetFirstMatch(file, fileContent, contentMatchSets, includeDebug);
}
}
}

View File

@@ -48,7 +48,7 @@ namespace BinaryObjectScanner.Protection
}
/// <inheritdoc/>
public IEnumerable<string> CheckDirectoryPath(string path, IEnumerable<string>? files)
public List<string> CheckDirectoryPath(string path, List<string>? files)
{
var matchers = new List<PathMatchSet>
{

View File

@@ -1,7 +1,9 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using BinaryObjectScanner.Interfaces;
using SabreTools.IO.Extensions;
using SabreTools.Matching;
using SabreTools.Matching.Paths;
using SabreTools.Serialization.Wrappers;
@@ -64,13 +66,9 @@ namespace BinaryObjectScanner.Protection
];
int endDosStub = (int)(pex.Model.Stub?.Header?.NewExeHeaderAddr ?? 0);
int position = -1;
#if NET20
bool containsCheck = Extensions.FirstPosition(pex.StubExecutableData ?? [], check, out position);
#else
bool containsCheck = pex.StubExecutableData?.FirstPosition(check, out position) ?? false;
#endif
// Check the executable tables
bool containsCheck = pex.StubExecutableData?.FirstPosition(check, out position) ?? false;
bool containsCheck2 = Array.Exists(pex.Model.ImportTable?.HintNameTable ?? [], hnte => hnte?.Name == "GetModuleHandleA")
&& Array.Exists(pex.Model.ImportTable?.HintNameTable ?? [], hnte => hnte?.Name == "GetProcAddress")
&& Array.Exists(pex.Model.ImportTable?.HintNameTable ?? [], hnte => hnte?.Name == "LoadLibraryA")
@@ -94,11 +92,7 @@ namespace BinaryObjectScanner.Protection
0x45, 0x4C, 0x33, 0x32, 0x2E, 0x64, 0x6C, 0x6C,
0x00, 0xEB, 0x79, 0x01, null, null, null, null,
];
#if NET20
containsCheck2 = Extensions.FirstPosition(pex.GetFirstSectionData(".text") ?? [], check2, out position2);
#else
containsCheck2 = pex.GetFirstSectionData(".text")?.FirstPosition(check2, out position2) ?? false;
#endif
}
else
{
@@ -118,7 +112,7 @@ namespace BinaryObjectScanner.Protection
}
/// <inheritdoc/>
public IEnumerable<string> CheckDirectoryPath(string path, IEnumerable<string>? files)
public List<string> CheckDirectoryPath(string path, List<string>? files)
{
var matchers = new List<PathMatchSet>
{
@@ -169,42 +163,14 @@ namespace BinaryObjectScanner.Protection
0x55, 0x6E, 0x6B, 0x6F, 0x77, 0x6E, 0x00, 0x55,
0x6E, 0x6B, 0x6F, 0x77, 0x6E
];
#if NET20
if (!Extensions.FirstPosition(sectionContent, check, out int position))
#else
if (!sectionContent.FirstPosition(check, out int position))
#endif
return "(Build unknown)";
string year, month, day;
if (versionTwo)
{
int index = position + 14;
int index = versionTwo ? position + 14 : position + 13;
byte[] temp = new byte[2];
Array.Copy(sectionContent, index, temp, 0, 2);
day = new string(Array.ConvertAll(temp, b => (char)b));
index += 3;
Array.Copy(sectionContent, index, temp, 0, 2);
month = new string(Array.ConvertAll(temp, b => (char)b));
index += 3;
Array.Copy(sectionContent, index, temp, 0, 2);
year = "20" + new string(Array.ConvertAll(temp, b => (char)b));
}
else
{
int index = position + 13;
byte[] temp = new byte[2];
Array.Copy(sectionContent, index, temp, 0, 2);
day = new string(Array.ConvertAll(temp, b => (char)b));
index += 3;
Array.Copy(sectionContent, index, temp, 0, 2);
month = new string(Array.ConvertAll(temp, b => (char)b));
index += 3;
Array.Copy(sectionContent, index, temp, 0, 2);
year = "20" + new string(Array.ConvertAll(temp, b => (char)b));
}
string day = Encoding.ASCII.GetString(sectionContent, index + 0, 2);
string month = Encoding.ASCII.GetString(sectionContent, index + 3, 2);
string year = "20" + Encoding.ASCII.GetString(sectionContent, index + 6, 2);
return $"(Build {year}-{month}-{day})";
}
@@ -215,9 +181,7 @@ namespace BinaryObjectScanner.Protection
if (sectionContent == null)
return null;
byte[] temp = new byte[4];
Array.Copy(sectionContent, position + 76, temp, 0, 4);
return new string(Array.ConvertAll(temp, b => (char)b));
return Encoding.ASCII.GetString(sectionContent, position + 76, 4);
}
public static string? GetVersion16Bit(string firstMatchedString, IEnumerable<string>? files)
@@ -226,16 +190,12 @@ namespace BinaryObjectScanner.Protection
return string.Empty;
using var fs = File.Open(firstMatchedString, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
using var br = new BinaryReader(fs);
return GetVersion16Bit(br.ReadBytes((int)fs.Length));
return GetVersion16Bit(fs.ReadBytes((int)fs.Length));
}
private static string GetVersion16Bit(byte[] fileContent)
{
byte[] temp = new byte[7];
Array.Copy(fileContent, 71, temp, 0, 7);
char[] version = Array.ConvertAll(temp, b => (char)b);
string version = Encoding.ASCII.GetString(fileContent, 71, 7);
if (char.IsNumber(version[0]) && char.IsNumber(version[2]) && char.IsNumber(version[3]))
{
if (char.IsNumber(version[5]) && char.IsNumber(version[6]))

View File

@@ -1,5 +1,4 @@
using System;
using System.Linq;
using BinaryObjectScanner.Interfaces;
using SabreTools.Serialization.Wrappers;
@@ -22,13 +21,11 @@ namespace BinaryObjectScanner.Protection
return $"MGI Registration {pex.GetInternalVersion()}";
// Found in "Register.dll" from "VideoWaveIII" in IA item "mgi-videowave-iii-version-3.00-mgi-software-2000".
var resources = pex.FindStringTableByEntry("MGI Registration");
if (resources.Any())
if (pex.FindStringTableByEntry("MGI Registration").Count > 0)
return "MGI Registration";
// Found in "Register.dll" in IA item "MGIPhotoSuite4.0AndPhotoVista2.02001".
resources = pex.FindStringTableByEntry("Register@register.mgisoft.com");
if (resources.Any())
if (pex.FindStringTableByEntry("Register@register.mgisoft.com").Count > 0)
return "MGI Registration";
return null;

View File

@@ -1,6 +1,5 @@
using System;
using System.Collections.Generic;
using System.Linq;
using SabreTools.Matching;
using SabreTools.Matching.Paths;
using SabreTools.Serialization.Wrappers;
@@ -35,7 +34,7 @@ namespace BinaryObjectScanner.Protection
public partial class Macrovision
{
/// <inheritdoc cref="Interfaces.IExecutableCheck{T}.CheckExecutable(string, T, bool)"/>
internal string? CDillaCheckExecutable(string file, NewExecutable nex, bool includeDebug)
internal static string? CDillaCheckExecutable(string file, NewExecutable nex, bool includeDebug)
{
// TODO: Implement NE checks for "CDILLA05", "CDILLA10", "CDILLA16", and "CDILLA40".
@@ -61,7 +60,7 @@ namespace BinaryObjectScanner.Protection
}
/// <inheritdoc cref="Interfaces.IExecutableCheck{T}.CheckExecutable(string, T, bool)"/>
internal string? CDillaCheckExecutable(string file, PortableExecutable pex, bool includeDebug)
internal static string? CDillaCheckExecutable(string file, PortableExecutable pex, bool includeDebug)
{
// Get the sections from the executable, if possible
var sections = pex.Model.SectionTable;
@@ -101,36 +100,21 @@ namespace BinaryObjectScanner.Protection
return $"C-Dilla License Management System Version {pex.ProductVersion}";
// Get string table resources
var resource = pex.FindStringTableByEntry("C-Dilla Licence Management System");
if (resource.Any())
if (pex.FindStringTableByEntry("C-Dilla Licence Management System").Count > 0)
return $"C-Dilla License Management System";
resource = pex.FindStringTableByEntry("C-DiIla Licence Management System");
if (resource.Any())
if (pex.FindStringTableByEntry("C-DiIla Licence Management System").Count > 0)
return $"C-Dilla License Management System";
resource = pex.FindStringTableByEntry("C-DILLA_BITMAP_NAMES_TAG");
if (resource.Any())
if (pex.FindStringTableByEntry("C-DILLA_BITMAP_NAMES_TAG").Count > 0)
return $"C-Dilla License Management System";
resource = pex.FindStringTableByEntry("C-DILLA_EDITABLE_STRINGS_TAG");
if (resource.Any())
if (pex.FindStringTableByEntry("C-DILLA_EDITABLE_STRINGS_TAG").Count > 0)
return $"C-Dilla License Management System";
resource = pex.FindStringTableByEntry("CdaLMS.exe");
if (resource.Any())
if (pex.FindStringTableByEntry("CdaLMS.exe").Count > 0)
return $"C-Dilla License Management System";
resource = pex.FindStringTableByEntry("cdilla51.dll");
if (resource.Any())
if (pex.FindStringTableByEntry("cdilla51.dll").Count > 0)
return $"C-Dilla License Management System";
resource = pex.FindStringTableByEntry("cdilla52.dll");
if (resource.Any())
if (pex.FindStringTableByEntry("cdilla52.dll").Count > 0)
return $"C-Dilla License Management System";
resource = pex.FindStringTableByEntry("http://www.c-dilla.com/support/lms.html");
if (resource.Any())
if (pex.FindStringTableByEntry("http://www.c-dilla.com/support/lms.html").Count > 0)
return $"C-Dilla License Management System";
// Get the .data/DATA section strings, if they exist
@@ -147,8 +131,8 @@ namespace BinaryObjectScanner.Protection
return null;
}
/// <inheritdoc cref="Interfaces.IPathCheck.CheckDirectoryPath(string, IEnumerable{string})"/>
internal IEnumerable<string> CDillaCheckDirectoryPath(string path, IEnumerable<string>? files)
/// <inheritdoc cref="Interfaces.IPathCheck.CheckDirectoryPath(string, List{string})"/>
internal static List<string> CDillaCheckDirectoryPath(string path, List<string>? files)
{
var matchers = new List<PathMatchSet>
{
@@ -191,7 +175,7 @@ namespace BinaryObjectScanner.Protection
}
/// <inheritdoc cref="Interfaces.IPathCheck.CheckFilePath(string)"/>
internal string? CDillaCheckFilePath(string path)
internal static string? CDillaCheckFilePath(string path)
{
var matchers = new List<PathMatchSet>
{

View File

@@ -31,7 +31,7 @@ namespace BinaryObjectScanner.Protection
public partial class Macrovision
{
/// <inheritdoc cref="Interfaces.IExecutableCheck{T}.CheckExecutable(string, T, bool)"/>
internal string? CactusDataShieldCheckExecutable(string file, PortableExecutable pex, bool includeDebug)
internal static string? CactusDataShieldCheckExecutable(string file, PortableExecutable pex, bool includeDebug)
{
// Get the sections from the executable, if possible
var sections = pex.Model.SectionTable;
@@ -44,15 +44,13 @@ namespace BinaryObjectScanner.Protection
{
if (strs.Exists(s => s.Contains("\\*.CDS")))
return "Cactus Data Shield 200";
if (strs.Exists(s => s.Contains("DATA.CDS")))
return "Cactus Data Shield 200";
}
// Found in "Volumia!" by Puur (Barcode 7 43218 63282 2) (Discogs Release Code [r795427]).
// Modified version of the PlayJ Music Player specificaly for CDS, as indicated by the About page present when running the executable.
var resources = pex.FindGenericResource("CactusPJ");
if (resources != null && resources.Any())
if (pex.FindGenericResource("CactusPJ").Count > 0)
return "PlayJ Music Player (Cactus Data Shield 200)";
// Found in various files in "Les Paul & Friends" (Barcode 4 98806 834170).
@@ -63,8 +61,8 @@ namespace BinaryObjectScanner.Protection
return null;
}
/// <inheritdoc cref="Interfaces.IPathCheck.CheckDirectoryPath(string, IEnumerable{string})"/>
internal IEnumerable<string> CactusDataShieldCheckDirectoryPath(string path, IEnumerable<string>? files)
/// <inheritdoc cref="Interfaces.IPathCheck.CheckDirectoryPath(string, List{string})"/>
internal static List<string> CactusDataShieldCheckDirectoryPath(string path, List<string>? files)
{
// TODO: Verify if these are OR or AND
var matchers = new List<PathMatchSet>
@@ -91,7 +89,7 @@ namespace BinaryObjectScanner.Protection
}
/// <inheritdoc cref="Interfaces.IPathCheck.CheckFilePath(string)"/>
internal string? CactusDataShieldCheckFilePath(string path)
internal static string? CactusDataShieldCheckFilePath(string path)
{
var matchers = new List<PathMatchSet>
{

View File

@@ -12,7 +12,7 @@ namespace BinaryObjectScanner.Protection
public partial class Macrovision
{
/// <inheritdoc cref="Interfaces.IExecutableCheck{T}.CheckExecutable(string, T, bool)"/>
internal string? FLEXnetCheckExecutable(string file, PortableExecutable pex, bool includeDebug)
internal static string? FLEXnetCheckExecutable(string file, PortableExecutable pex, bool includeDebug)
{
// Get the sections from the executable, if possible
var sections = pex.Model.SectionTable;
@@ -67,8 +67,8 @@ namespace BinaryObjectScanner.Protection
return null;
}
/// <inheritdoc cref="Interfaces.IPathCheck.CheckDirectoryPath(string, IEnumerable{string})"/>
internal IEnumerable<string> FLEXNetCheckDirectoryPath(string path, IEnumerable<string>? files)
/// <inheritdoc cref="Interfaces.IPathCheck.CheckDirectoryPath(string, List{string})"/>
internal static List<string> FLEXNetCheckDirectoryPath(string path, List<string>? files)
{
var matchers = new List<PathMatchSet>
{
@@ -88,7 +88,7 @@ namespace BinaryObjectScanner.Protection
}
/// <inheritdoc cref="Interfaces.IPathCheck.CheckFilePath(string)"/>
internal string? FLEXNetCheckFilePath(string path)
internal static string? FLEXNetCheckFilePath(string path)
{
var matchers = new List<PathMatchSet>
{

View File

@@ -19,7 +19,7 @@ namespace BinaryObjectScanner.Protection
public partial class Macrovision
{
/// <inheritdoc cref="Interfaces.IExecutableCheck{T}.CheckExecutable(string, T, bool)"/>
internal string? RipGuardCheckExecutable(string file, PortableExecutable pex, bool includeDebug)
internal static string? RipGuardCheckExecutable(string file, PortableExecutable pex, bool includeDebug)
{
// Get the sections from the executable, if possible
var sections = pex.Model.SectionTable;
@@ -50,16 +50,14 @@ namespace BinaryObjectScanner.Protection
return "RipGuard";
}
}
catch
{
}
catch { }
}
return null;
}
/// <inheritdoc cref="Interfaces.IPathCheck.CheckDirectoryPath(string, IEnumerable{string})"/>
internal IEnumerable<string> RipGuardCheckDirectoryPath(string path, IEnumerable<string>? files)
/// <inheritdoc cref="Interfaces.IPathCheck.CheckDirectoryPath(string, List{string})"/>
internal static List<string> RipGuardCheckDirectoryPath(string path, List<string>? files)
{
var matchers = new List<PathMatchSet>
{
@@ -75,7 +73,7 @@ namespace BinaryObjectScanner.Protection
}
/// <inheritdoc cref="Interfaces.IPathCheck.CheckFilePath(string)"/>
internal string? RipGuardCheckFilePath(string path)
internal static string? RipGuardCheckFilePath(string path)
{
var matchers = new List<PathMatchSet>
{

View File

@@ -1,6 +1,5 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using SabreTools.Matching;
using SabreTools.Matching.Content;
@@ -41,7 +40,7 @@ namespace BinaryObjectScanner.Protection
public partial class Macrovision
{
/// <inheritdoc cref="Interfaces.IExecutableCheck{T}.CheckExecutable(string, T, bool)"/>
internal string? SafeCastCheckExecutable(string file, NewExecutable nex, bool includeDebug)
internal static string? SafeCastCheckExecutable(string file, NewExecutable nex, bool includeDebug)
{
// Check for the CDAC01AA name string.
if (nex.Model.ResidentNameTable != null)
@@ -68,7 +67,7 @@ namespace BinaryObjectScanner.Protection
}
/// <inheritdoc cref="Interfaces.IExecutableCheck{T}.CheckExecutable(string, T, bool)"/>
internal string? SafeCastCheckExecutable(string file, PortableExecutable pex, bool includeDebug)
internal static string? SafeCastCheckExecutable(string file, PortableExecutable pex, bool includeDebug)
{
// Get the sections from the executable, if possible
var sections = pex.Model.SectionTable;
@@ -91,8 +90,7 @@ namespace BinaryObjectScanner.Protection
// Get the dialog box resources
// Found in "CDAC21BA.DLL" in Redump entry 95524.
var resource = pex.FindDialogByTitle("SafeCast API");
if (resource.Any())
if (pex.FindDialogByTitle("SafeCast API").Count > 0)
return "SafeCast";
// Get the .data/DATA section strings, if they exist
@@ -148,8 +146,8 @@ namespace BinaryObjectScanner.Protection
return null;
}
/// <inheritdoc cref="Interfaces.IPathCheck.CheckDirectoryPath(string, IEnumerable{string})"/>
internal IEnumerable<string> SafeCastCheckDirectoryPath(string path, IEnumerable<string>? files)
/// <inheritdoc cref="Interfaces.IPathCheck.CheckDirectoryPath(string, List{string})"/>
internal static List<string> SafeCastCheckDirectoryPath(string path, List<string>? files)
{
var matchers = new List<PathMatchSet>
{
@@ -192,7 +190,7 @@ namespace BinaryObjectScanner.Protection
}
/// <inheritdoc cref="Interfaces.IPathCheck.CheckFilePath(string)"/>
internal string? SafeCastCheckFilePath(string path)
internal static string? SafeCastCheckFilePath(string path)
{
var matchers = new List<PathMatchSet>
{

View File

@@ -1,7 +1,6 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using SabreTools.Hashing;
using SabreTools.Matching;
using SabreTools.Matching.Paths;
@@ -42,7 +41,7 @@ namespace BinaryObjectScanner.Protection
public partial class Macrovision
{
/// <inheritdoc cref="Interfaces.IExecutableCheck{T}.CheckExecutable(string, T, bool)"/>
internal string? SafeDiscCheckExecutable(string file, PortableExecutable pex, bool includeDebug)
internal static string? SafeDiscCheckExecutable(string file, PortableExecutable pex, bool includeDebug)
{
// Get the sections from the executable, if possible
var sections = pex.Model.SectionTable;
@@ -50,12 +49,18 @@ namespace BinaryObjectScanner.Protection
return null;
// Found in Redump entry 57986.
if (Array.Exists(pex.Model.ImportTable?.HintNameTable ?? [], ihne => ihne?.Name == "LTDLL_Authenticate"))
return "SafeDisc Lite";
if (pex.Model.ImportTable?.HintNameTable != null)
{
if (Array.Exists(pex.Model.ImportTable.HintNameTable, ihne => ihne?.Name == "LTDLL_Authenticate"))
return "SafeDisc Lite";
}
// Found in Redump entry 57986.
if (Array.Exists(pex.Model.ImportTable?.ImportDirectoryTable ?? [], idte => idte?.Name == "ltdll.dll"))
return "SafeDisc Lite";
if (pex.Model.ImportTable?.ImportDirectoryTable != null)
{
if (Array.Exists(pex.Model.ImportTable.ImportDirectoryTable, idte => idte?.Name == "ltdll.dll"))
return "SafeDisc Lite";
}
// Get the .data/DATA section strings, if they exist
var strs = pex.GetFirstSectionStrings(".data") ?? pex.GetFirstSectionStrings("DATA");
@@ -104,12 +109,10 @@ namespace BinaryObjectScanner.Protection
// Found in Redump entries 20729 and 65569.
// Get the debug data
try
{
if (pex.FindCodeViewDebugTableByPath("SafeDisc").Any() || pex.FindCodeViewDebugTableByPath("Safedisk").Any())
return "SafeDisc";
}
catch { }
if (pex.FindCodeViewDebugTableByPath("SafeDisc").Count > 0)
return "SafeDisc";
if (pex.FindCodeViewDebugTableByPath("Safedisk").Count > 0)
return "SafeDisc";
// TODO: Investigate various section names:
// "STLPORT_" - Found in Redump entry 11638.
@@ -124,8 +127,8 @@ namespace BinaryObjectScanner.Protection
return null;
}
/// <inheritdoc cref="Interfaces.IPathCheck.CheckDirectoryPath(string, IEnumerable{string})"/>
internal IEnumerable<string> SafeDiscCheckDirectoryPath(string path, IEnumerable<string>? files)
/// <inheritdoc cref="Interfaces.IPathCheck.CheckDirectoryPath(string, List{string})"/>
internal static List<string> SafeDiscCheckDirectoryPath(string path, List<string>? files)
{
var matchers = new List<PathMatchSet>
{
@@ -263,7 +266,7 @@ namespace BinaryObjectScanner.Protection
}
/// <inheritdoc cref="Interfaces.IPathCheck.CheckFilePath(string)"/>
internal string? SafeDiscCheckFilePath(string path)
internal static string? SafeDiscCheckFilePath(string path)
{
var matchers = new List<PathMatchSet>
{
@@ -926,7 +929,7 @@ namespace BinaryObjectScanner.Protection
// "SPLSH256.BMP": Found in SafeDisc versions 1.00.025-1.01.044 (Redump entries 66005 and 81619).
}
private string GetSafeDiscDiagExecutableVersion(PortableExecutable pex)
private static string GetSafeDiscDiagExecutableVersion(PortableExecutable pex)
{
// Different versions of this executable correspond to different SafeDisc versions.
var version = pex.FileVersion;

View File

@@ -70,23 +70,17 @@ namespace BinaryObjectScanner.Protection
// Almost every single sample known has both sections, though one only contains the "stxt371" section. It is unknown if this is intentional, or if the game functions without it.
// It is present in the "Texas HoldEm!" game in "boontybox_PCGamer_DVD.exe" in IA items PC_Gamer_Disc_7.55_July_2005 and cdrom-pcgamercd7.58.
// Other games in this set also aren't functional despite having the normal layout of stxt sections, and the primary program doesn't install at all due to activation servers being down.
bool stxt371Section = pex.ContainsSection("stxt371", exact: true);
bool stxt774Section = pex.ContainsSection("stxt774", exact: true);
if (stxt371Section || stxt774Section)
if (pex.ContainsSection("stxt371", exact: true) || pex.ContainsSection("stxt774", exact: true))
{
// Check the header padding for protected sections.
var sectionMatch = CheckSectionForProtection(file, includeDebug, pex.HeaderPaddingStrings, pex.HeaderPaddingData, true);
if (!string.IsNullOrEmpty(sectionMatch))
{
if (sectionMatch != null)
resultsList.Add(sectionMatch);
// Get the .data section, if it exists, for protected sections.
sectionMatch = CheckSectionForProtection(file, includeDebug, pex.GetFirstSectionStrings(".data"), pex.GetFirstSectionData(".data"), true);
if (sectionMatch != null)
resultsList.Add(sectionMatch!);
}
else
{
// Get the .data section, if it exists, for protected sections.
sectionMatch = CheckSectionForProtection(file, includeDebug, pex.GetFirstSectionStrings(".data"), pex.GetFirstSectionData(".data"), true);
if (!string.IsNullOrEmpty(sectionMatch))
resultsList.Add(sectionMatch!);
}
int entryPointIndex = pex.FindEntryPointSectionIndex();
var entryPointSectionName = pex.SectionNames?[entryPointIndex];
@@ -113,17 +107,13 @@ namespace BinaryObjectScanner.Protection
{
// Check the header padding for protected sections.
var sectionMatch = CheckSectionForProtection(file, includeDebug, pex.HeaderPaddingStrings, pex.HeaderPaddingData, false);
if (!string.IsNullOrEmpty(sectionMatch))
{
resultsList.Add(sectionMatch!);
}
else
{
// Check the .data section, if it exists, for protected sections.
sectionMatch = CheckSectionForProtection(file, includeDebug, pex.GetFirstSectionStrings(".data"), pex.GetFirstSectionData(".data"), false);
if (!string.IsNullOrEmpty(sectionMatch))
resultsList.Add(sectionMatch!);
}
if (sectionMatch != null)
resultsList.Add(sectionMatch);
// Check the .data section, if it exists, for protected sections.
sectionMatch = CheckSectionForProtection(file, includeDebug, pex.GetFirstSectionStrings(".data"), pex.GetFirstSectionData(".data"), false);
if (sectionMatch != null)
resultsList.Add(sectionMatch);
}
// Run Cactus Data Shield PE checks
@@ -165,7 +155,7 @@ namespace BinaryObjectScanner.Protection
}
/// <inheritdoc/>
public IEnumerable<string> CheckDirectoryPath(string path, IEnumerable<string>? files)
public List<string> CheckDirectoryPath(string path, List<string>? files)
{
var results = new List<string>();
@@ -248,8 +238,8 @@ namespace BinaryObjectScanner.Protection
return null;
}
/// <inheritdoc cref="IPathCheck.CheckDirectoryPath(string, IEnumerable{string})"/>
internal IEnumerable<string> MacrovisionCheckDirectoryPath(string path, IEnumerable<string>? files)
/// <inheritdoc cref="IPathCheck.CheckDirectoryPath(string, List{string})"/>
internal static List<string> MacrovisionCheckDirectoryPath(string path, List<string>? files)
{
var matchers = new List<PathMatchSet>
{
@@ -261,7 +251,7 @@ namespace BinaryObjectScanner.Protection
}
/// <inheritdoc cref="IPathCheck.CheckFilePath(string)"/>
internal string? MacrovisionCheckFilePath(string path)
internal static string? MacrovisionCheckFilePath(string path)
{
var matchers = new List<PathMatchSet>
{

View File

@@ -37,7 +37,7 @@ namespace BinaryObjectScanner.Protection
}
/// <inheritdoc/>
public IEnumerable<string> CheckDirectoryPath(string path, IEnumerable<string>? files)
public List<string> CheckDirectoryPath(string path, List<string>? files)
{
var matchers = new List<PathMatchSet>
{

View File

@@ -1,6 +1,5 @@
using System;
using System.Collections.Generic;
using System.Linq;
using BinaryObjectScanner.Interfaces;
using SabreTools.Matching;
using SabreTools.Matching.Paths;
@@ -33,12 +32,10 @@ namespace BinaryObjectScanner.Protection
if (name?.StartsWith("LicGen Module", StringComparison.OrdinalIgnoreCase) == true)
return $"MediaMax CD-3";
var cd3CtrlResources = pex.FindGenericResource("Cd3Ctl");
if (cd3CtrlResources.Any())
if (pex.FindGenericResource("Cd3Ctl").Count > 0)
return $"MediaMax CD-3";
var limitedProductionResources = pex.FindDialogBoxByItemTitle("This limited production advanced CD is not playable on your computer. It is solely intended for playback on standard CD players.");
if (limitedProductionResources.Any())
if (pex.FindDialogBoxByItemTitle("This limited production advanced CD is not playable on your computer. It is solely intended for playback on standard CD players.").Count > 0)
return $"MediaMax CD-3";
// TODO: Investigate the following dialog item title resource
@@ -63,7 +60,7 @@ namespace BinaryObjectScanner.Protection
}
/// <inheritdoc/>
public IEnumerable<string> CheckDirectoryPath(string path, IEnumerable<string>? files)
public List<string> CheckDirectoryPath(string path, List<string>? files)
{
var matchers = new List<PathMatchSet>
{

View File

@@ -32,11 +32,7 @@ namespace BinaryObjectScanner.Protection
// Get the .neac0 and .neac1 sections, if they exist.
// Found in "NeacSafe64.sys" and "NeacSafe.sys".
bool neac0Section = pex.ContainsSection(".neac0", exact: true);
bool neac1Section = pex.ContainsSection(".neac1", exact: true);
// Check if either .neac section is present.
if (neac0Section || neac1Section)
if (pex.ContainsSection(".neac0", exact: true) || pex.ContainsSection(".neac1", exact: true))
return "NEAC Protect";
var name = pex.ProductName;
@@ -50,7 +46,7 @@ namespace BinaryObjectScanner.Protection
}
/// <inheritdoc/>
public IEnumerable<string> CheckDirectoryPath(string path, IEnumerable<string>? files)
public List<string> CheckDirectoryPath(string path, List<string>? files)
{
var matchers = new List<PathMatchSet>
{

View File

@@ -80,7 +80,7 @@ namespace BinaryObjectScanner.Protection
}
/// <inheritdoc/>
public IEnumerable<string> CheckDirectoryPath(string path, IEnumerable<string>? files)
public List<string> CheckDirectoryPath(string path, List<string>? files)
{
var matchers = new List<PathMatchSet>
{

View File

@@ -64,7 +64,7 @@ namespace BinaryObjectScanner.Protection
}
/// <inheritdoc/>
public IEnumerable<string> CheckDirectoryPath(string path, IEnumerable<string>? files)
public List<string> CheckDirectoryPath(string path, List<string>? files)
{
var matchers = new List<PathMatchSet>
{

View File

@@ -29,7 +29,7 @@ namespace BinaryObjectScanner.Protection
}
/// <inheritdoc/>
public IEnumerable<string> CheckDirectoryPath(string path, IEnumerable<string>? files)
public List<string> CheckDirectoryPath(string path, List<string>? files)
{
var matchers = new List<PathMatchSet>
{

View File

@@ -40,7 +40,7 @@ namespace BinaryObjectScanner.Protection
}
/// <inheritdoc/>
public IEnumerable<string> CheckDirectoryPath(string path, IEnumerable<string>? files)
public List<string> CheckDirectoryPath(string path, List<string>? files)
{
var matchers = new List<PathMatchSet>
{

View File

@@ -1,6 +1,5 @@
using System.Collections.Generic;
using System.IO;
using System.Linq;
using BinaryObjectScanner.Interfaces;
namespace BinaryObjectScanner.Protection
@@ -9,7 +8,7 @@ namespace BinaryObjectScanner.Protection
public class ProtectDVDVideo : IPathCheck
{
/// <inheritdoc/>
public IEnumerable<string> CheckDirectoryPath(string path, IEnumerable<string>? files)
public List<string> CheckDirectoryPath(string path, List<string>? files)
{
var protections = new List<string>();
if (files == null)
@@ -17,8 +16,8 @@ namespace BinaryObjectScanner.Protection
if (Directory.Exists(Path.Combine(path, "VIDEO_TS")))
{
string[] ifofiles = files.Where(s => s.EndsWith(".ifo")).ToArray();
for (int i = 0; i < ifofiles.Length; i++)
var ifofiles = files.FindAll(s => s.EndsWith(".ifo"));
for (int i = 0; i < ifofiles.Count; i++)
{
var ifofile = new FileInfo(ifofiles[i]);
if (ifofile.Length == 0)

Some files were not shown because too many files have changed in this diff Show More