mirror of
https://github.com/SabreTools/BinaryObjectScanner.git
synced 2026-02-12 05:35:17 +00:00
Compare commits
16 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
cdc9171615 | ||
|
|
21451c5294 | ||
|
|
dea35ca158 | ||
|
|
7d96e7b333 | ||
|
|
4f493626cb | ||
|
|
03a2dff668 | ||
|
|
0d213274b5 | ||
|
|
80d3b8d8bb | ||
|
|
e788ad9287 | ||
|
|
c70b5f6ec8 | ||
|
|
6b7ad781b7 | ||
|
|
9d60a4d1ec | ||
|
|
ec091ada95 | ||
|
|
c2547295bf | ||
|
|
58707feb72 | ||
|
|
7efe622990 |
@@ -1,4 +1,4 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFrameworks>net6.0;net8.0;net9.0</TargetFrameworks>
|
||||
@@ -17,7 +17,7 @@
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.12.0" />
|
||||
<PackageReference Include="SabreTools.Serialization" Version="1.8.0" />
|
||||
<PackageReference Include="SabreTools.Serialization" Version="1.8.1" />
|
||||
<PackageReference Include="xunit" Version="2.9.2" />
|
||||
<PackageReference Include="xunit.runner.visualstudio" Version="2.8.2">
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
|
||||
@@ -3,7 +3,7 @@ using Xunit;
|
||||
|
||||
namespace BinaryObjectScanner.Test
|
||||
{
|
||||
public class ScannerTests
|
||||
public class ProtectionDictionaryTests
|
||||
{
|
||||
#region ProcessProtectionString
|
||||
|
||||
@@ -11,7 +11,7 @@ namespace BinaryObjectScanner.Test
|
||||
public void ProcessProtectionString_Null_Empty()
|
||||
{
|
||||
string? protection = null;
|
||||
List<string> actual = Scanner.ProcessProtectionString(protection);
|
||||
List<string> actual = ProtectionDictionary.ProcessProtectionString(protection);
|
||||
Assert.Empty(actual);
|
||||
}
|
||||
|
||||
@@ -19,7 +19,7 @@ namespace BinaryObjectScanner.Test
|
||||
public void ProcessProtectionString_Empty_Empty()
|
||||
{
|
||||
string? protection = string.Empty;
|
||||
List<string> actual = Scanner.ProcessProtectionString(protection);
|
||||
List<string> actual = ProtectionDictionary.ProcessProtectionString(protection);
|
||||
Assert.Empty(actual);
|
||||
}
|
||||
|
||||
@@ -27,7 +27,7 @@ namespace BinaryObjectScanner.Test
|
||||
public void ProcessProtectionString_NoIndicator_Single()
|
||||
{
|
||||
string? protection = "item1";
|
||||
List<string> actual = Scanner.ProcessProtectionString(protection);
|
||||
List<string> actual = ProtectionDictionary.ProcessProtectionString(protection);
|
||||
Assert.Single(actual);
|
||||
}
|
||||
|
||||
@@ -35,7 +35,7 @@ namespace BinaryObjectScanner.Test
|
||||
public void ProcessProtectionString_Indicator_Multiple()
|
||||
{
|
||||
string? protection = "item1;item2";
|
||||
List<string> actual = Scanner.ProcessProtectionString(protection);
|
||||
List<string> actual = ProtectionDictionary.ProcessProtectionString(protection);
|
||||
Assert.Equal(2, actual.Count);
|
||||
}
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
<Nullable>enable</Nullable>
|
||||
<SuppressTfmSupportBuildWarnings>true</SuppressTfmSupportBuildWarnings>
|
||||
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
|
||||
<Version>3.3.0</Version>
|
||||
<Version>3.3.1</Version>
|
||||
<!-- Mostly added due to external libraries -->
|
||||
<WarningsNotAsErrors>CS8600;CS8601;CS8602;CS8603;CS8604;CS8605;CS8618;CS8625;CS8634;CS8765;IL3000;NU5100</WarningsNotAsErrors>
|
||||
|
||||
@@ -92,9 +92,9 @@
|
||||
<PackageReference Include="SabreTools.IO" Version="1.6.1" />
|
||||
<PackageReference Include="SabreTools.Matching" Version="1.5.0" />
|
||||
<PackageReference Include="SabreTools.Models" Version="1.5.5" />
|
||||
<PackageReference Include="SabreTools.Serialization" Version="1.8.0" />
|
||||
<PackageReference Include="UnshieldSharp" Version="1.9.1" />
|
||||
<PackageReference Include="WiseUnpacker" Version="1.5.1" />
|
||||
<PackageReference Include="SabreTools.Serialization" Version="1.8.1" />
|
||||
<PackageReference Include="UnshieldSharp" Version="1.9.2" />
|
||||
<PackageReference Include="WiseUnpacker" Version="1.5.4" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
@@ -30,6 +30,9 @@ namespace BinaryObjectScanner.FileType
|
||||
// Not supported for .NET Framework 2.0 or .NET Framework 3.5 due to library support
|
||||
return false;
|
||||
#else
|
||||
if (stream == null || !stream.CanRead)
|
||||
return false;
|
||||
|
||||
try
|
||||
{
|
||||
using var msi = new CompoundFile(stream, CFSUpdateMode.ReadOnly, CFSConfiguration.Default);
|
||||
|
||||
@@ -25,6 +25,9 @@ namespace BinaryObjectScanner.FileType
|
||||
{
|
||||
try
|
||||
{
|
||||
if (!File.Exists(file))
|
||||
return false;
|
||||
|
||||
var archive = new ISv3(file);
|
||||
foreach (var cfile in archive.Files)
|
||||
{
|
||||
@@ -39,10 +42,8 @@ namespace BinaryObjectScanner.FileType
|
||||
if (fileContents == null || !string.IsNullOrEmpty(error))
|
||||
continue;
|
||||
|
||||
using (FileStream fs = File.OpenWrite(tempFile))
|
||||
{
|
||||
fs.Write(fileContents, 0, fileContents.Length);
|
||||
}
|
||||
using FileStream fs = File.OpenWrite(tempFile);
|
||||
fs.Write(fileContents, 0, fileContents.Length);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
|
||||
@@ -54,6 +54,9 @@ namespace BinaryObjectScanner.FileType
|
||||
|
||||
try
|
||||
{
|
||||
if (!File.Exists(file))
|
||||
return false;
|
||||
|
||||
var cabfile = InstallShieldCabinet.Open(file);
|
||||
if (cabfile?.HeaderList == null)
|
||||
return false;
|
||||
@@ -77,6 +80,10 @@ namespace BinaryObjectScanner.FileType
|
||||
tempFile = Path.Combine(outDir, $"BAD_FILENAME{i}");
|
||||
}
|
||||
|
||||
var directoryName = Path.GetDirectoryName(tempFile);
|
||||
if (directoryName != null && !Directory.Exists(directoryName))
|
||||
Directory.CreateDirectory(directoryName);
|
||||
|
||||
cabfile.FileSave(i, tempFile);
|
||||
}
|
||||
catch (Exception ex)
|
||||
|
||||
@@ -32,6 +32,9 @@ namespace BinaryObjectScanner.FileType
|
||||
#else
|
||||
try
|
||||
{
|
||||
if (!File.Exists(file))
|
||||
return false;
|
||||
|
||||
// Try to open the archive and listfile
|
||||
var mpqArchive = new MpqArchive(file, FileAccess.Read);
|
||||
string? listfile = null;
|
||||
|
||||
@@ -33,6 +33,9 @@ namespace BinaryObjectScanner.FileType
|
||||
#else
|
||||
try
|
||||
{
|
||||
if (!File.Exists(file))
|
||||
return false;
|
||||
|
||||
// Loop over each entry
|
||||
var cabArchive = new MSCabinet(file);
|
||||
foreach (var compressedFile in cabArchive.GetFiles())
|
||||
|
||||
@@ -24,6 +24,9 @@ namespace BinaryObjectScanner.FileType
|
||||
/// <inheritdoc/>
|
||||
public bool Extract(Stream? stream, string file, string outDir, bool includeDebug)
|
||||
{
|
||||
if (stream == null || !stream.CanRead)
|
||||
return false;
|
||||
|
||||
try
|
||||
{
|
||||
var data = Decompressor.Decompress(stream);
|
||||
|
||||
@@ -42,7 +42,12 @@ namespace BinaryObjectScanner.FileType
|
||||
try
|
||||
{
|
||||
var readerOptions = new ReaderOptions() { LookForHeader = lookForHeader };
|
||||
using var zipFile = ZipArchive.Open(stream, readerOptions);
|
||||
var zipFile = ZipArchive.Open(stream, readerOptions);
|
||||
|
||||
// Try to read the file path if no entries are found
|
||||
if (zipFile.Entries.Count == 0 && !string.IsNullOrEmpty(file) && File.Exists(file))
|
||||
zipFile = ZipArchive.Open(file, readerOptions);
|
||||
|
||||
foreach (var entry in zipFile.Entries)
|
||||
{
|
||||
try
|
||||
|
||||
@@ -42,7 +42,12 @@ namespace BinaryObjectScanner.FileType
|
||||
try
|
||||
{
|
||||
var readerOptions = new ReaderOptions() { LookForHeader = lookForHeader };
|
||||
using RarArchive rarFile = RarArchive.Open(stream, readerOptions);
|
||||
RarArchive rarFile = RarArchive.Open(stream, readerOptions);
|
||||
|
||||
// Try to read the file path if no entries are found
|
||||
if (rarFile.Entries.Count == 0 && !string.IsNullOrEmpty(file) && File.Exists(file))
|
||||
rarFile = RarArchive.Open(file, readerOptions);
|
||||
|
||||
if (!rarFile.IsComplete)
|
||||
return false;
|
||||
|
||||
|
||||
@@ -42,7 +42,12 @@ namespace BinaryObjectScanner.FileType
|
||||
try
|
||||
{
|
||||
var readerOptions = new ReaderOptions() { LookForHeader = lookForHeader };
|
||||
using var sevenZip = SevenZipArchive.Open(stream, readerOptions);
|
||||
var sevenZip = SevenZipArchive.Open(stream, readerOptions);
|
||||
|
||||
// Try to read the file path if no entries are found
|
||||
if (sevenZip.Entries.Count == 0 && !string.IsNullOrEmpty(file) && File.Exists(file))
|
||||
sevenZip = SevenZipArchive.Open(file, readerOptions);
|
||||
|
||||
foreach (var entry in sevenZip.Entries)
|
||||
{
|
||||
try
|
||||
|
||||
@@ -32,7 +32,12 @@ namespace BinaryObjectScanner.FileType
|
||||
#if NET462_OR_GREATER || NETCOREAPP
|
||||
try
|
||||
{
|
||||
using var tarFile = TarArchive.Open(stream);
|
||||
var tarFile = TarArchive.Open(stream);
|
||||
|
||||
// Try to read the file path if no entries are found
|
||||
if (tarFile.Entries.Count == 0 && !string.IsNullOrEmpty(file) && File.Exists(file))
|
||||
tarFile = TarArchive.Open(file);
|
||||
|
||||
foreach (var entry in tarFile.Entries)
|
||||
{
|
||||
try
|
||||
|
||||
@@ -26,6 +26,9 @@ namespace BinaryObjectScanner.FileType
|
||||
public bool Extract(Stream? stream, string file, string outDir, bool includeDebug)
|
||||
{
|
||||
#if NET462_OR_GREATER || NETCOREAPP
|
||||
if (stream == null || !stream.CanRead)
|
||||
return false;
|
||||
|
||||
try
|
||||
{
|
||||
// Try opening the stream
|
||||
|
||||
@@ -7,6 +7,7 @@ using SabreTools.Serialization.Wrappers;
|
||||
namespace BinaryObjectScanner.Packer
|
||||
{
|
||||
// TODO: Add extraction
|
||||
// TODO: Research and add support for ASProtect. It seems to be an additional layer of protection for ASPack, making detecting it separately more difficult.
|
||||
public class ASPack : IExtractableExecutable<PortableExecutable>
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
@@ -35,6 +36,16 @@ namespace BinaryObjectScanner.Packer
|
||||
return match;
|
||||
}
|
||||
|
||||
// Get the .data/DATA section, if it exists
|
||||
var dataSectionRaw = pex.GetFirstSectionData(".data") ?? pex.GetFirstSectionData("DATA");
|
||||
if (dataSectionRaw != null)
|
||||
{
|
||||
var matchers = GenerateMatchers();
|
||||
var match = MatchUtil.GetFirstMatch(file, dataSectionRaw, matchers, includeDebug);
|
||||
if (!string.IsNullOrEmpty(match))
|
||||
return match;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -552,6 +563,38 @@ namespace BinaryObjectScanner.Packer
|
||||
0x1C, 0x00
|
||||
}, "ASPack 2.x (without Poly) -> Solodovnikov Alexey"),
|
||||
|
||||
// Commented out due to "ASPack 2.1" getting detected before this. More research is needed.
|
||||
// Based on detection rules from https://github.com/x64dbg/yarasigs/blob/master/Old_Internal_PEiD.yara
|
||||
/* new(new byte?[]
|
||||
{
|
||||
0x60, 0xE8, 0x03, 0x00, 0x00, 0x00, 0xE9, 0xEB,
|
||||
0x04, 0x5D, 0x45, 0x55, 0xC3, 0xE8, 0x01, 0x00,
|
||||
0x00, 0x00, 0xEB, 0x5D, 0xBB, 0xED, 0xFF, 0xFF,
|
||||
0xFF, 0x03, 0xDD, 0x81, 0xEB, 0x00, null, null,
|
||||
null, 0x80, 0x7D, 0x4D, 0x01, 0x75, 0x0C, 0x8B,
|
||||
0x74, 0x24, 0x28, 0x83, 0xFE, 0x01, 0x89, 0x5D,
|
||||
0x4E, 0x75, 0x31, 0x8D, 0x45, 0x53, 0x50, 0x53,
|
||||
0xFF, 0xB5, null, 0x09, 0x00, 0x00, 0x8D, 0x45,
|
||||
0x35, 0x50, 0xE9, 0x82, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, null,
|
||||
0x00, 0x00, 0x00, 0x00, 0xB8, 0xF8, 0xC0, 0xA5,
|
||||
0x23, 0x50, 0x50, 0x03, 0x45, 0x4E, 0x5B, 0x85,
|
||||
0xC0, 0x74, 0x1C, 0xEB, 0x01, 0xE8, 0x81, 0xFB,
|
||||
0xF8, 0xC0, 0xA5, 0x23, 0x74, 0x35, 0x33, 0xD2,
|
||||
0x56, 0x6A, 0x00, 0x56, 0xFF, 0x75, 0x4E, 0xFF,
|
||||
0xD0, 0x5E, 0x83, 0xFE, 0x00, 0x75, 0x24, 0x33,
|
||||
0xD2, 0x8B, 0x45, 0x41, 0x85, 0xC0, 0x74, 0x07,
|
||||
0x52, 0x52, 0xFF, 0x75, 0x35, 0xFF, 0xD0, 0x8B,
|
||||
0x45, 0x35, 0x85, 0xC0, 0x74, 0x0D, 0x68, 0x00,
|
||||
0x80, 0x00, 0x00, 0x6A, 0x00, 0xFF, 0x75, 0x35,
|
||||
0xFF, 0x55, 0x3D, 0x5B, 0x0B, 0xDB, 0x61, 0x75,
|
||||
0x06, 0x6A, 0x01, 0x58, 0xC2, 0x0C, 0x00, 0x33,
|
||||
0xC0, 0xF7, 0xD8, 0x1B, 0xC0, 0x40, 0xC2, 0x0C,
|
||||
0x00
|
||||
}, "ASProtect SKE 2.x -> Solodovnikov Alexey"), */
|
||||
|
||||
#endregion
|
||||
|
||||
#region 2.xx (Long)
|
||||
@@ -578,7 +621,8 @@ namespace BinaryObjectScanner.Packer
|
||||
|
||||
#region Short
|
||||
|
||||
new(new byte?[] { 0x75, 0x00, 0xE9 }, "ASPack 1.05b"),
|
||||
// Disabled due to being too prone to false positives.
|
||||
// new(new byte?[] { 0x75, 0x00, 0xE9 }, "ASPack 1.05b"),
|
||||
|
||||
new(new byte?[] { 0x90, 0x90, 0x90, 0x75, 0x00, 0xE9 }, "ASPack 1.06.1b"),
|
||||
|
||||
|
||||
@@ -22,18 +22,29 @@ namespace BinaryObjectScanner.Packer
|
||||
{
|
||||
if (value == null || value is not byte[] ba)
|
||||
continue;
|
||||
if (!ba.StartsWith(SabreTools.Models.PKZIP.Constants.LocalFileHeaderSignatureBytes))
|
||||
continue;
|
||||
|
||||
return "Embedded Archive";
|
||||
if (ba.StartsWith([0x37, 0x7A, 0xBC, 0xAF, 0x27, 0x1C]))
|
||||
return "Embedded 7-Zip Archive";
|
||||
if (ba.StartsWith(SabreTools.Models.PKZIP.Constants.LocalFileHeaderSignatureBytes))
|
||||
return "Embedded PKZIP Archive";
|
||||
if (ba.StartsWith([0x52, 0x61, 0x72, 0x21, 0x1A, 0x07, 0x00]))
|
||||
return "Embedded RAR Archive";
|
||||
if (ba.StartsWith([0x52, 0x61, 0x72, 0x21, 0x1A, 0x07, 0x01, 0x00]))
|
||||
return "Embedded RAR Archive";
|
||||
}
|
||||
}
|
||||
|
||||
// Check the overlay, if it exists
|
||||
if (pex.OverlayData != null && pex.OverlayData.Length > 0)
|
||||
{
|
||||
if (pex.OverlayData.StartsWith([0x37, 0x7A, 0xBC, 0xAF, 0x27, 0x1C]))
|
||||
return "Embedded 7-Zip Archive";
|
||||
if (pex.OverlayData.StartsWith(SabreTools.Models.PKZIP.Constants.LocalFileHeaderSignatureBytes))
|
||||
return "Embedded Archive";
|
||||
return "Embedded PKZIP Archive";
|
||||
if (pex.OverlayData.StartsWith([0x52, 0x61, 0x72, 0x21, 0x1A, 0x07, 0x00]))
|
||||
return "Embedded RAR Archive";
|
||||
if (pex.OverlayData.StartsWith([0x52, 0x61, 0x72, 0x21, 0x1A, 0x07, 0x01, 0x00]))
|
||||
return "Embedded RAR Archive";
|
||||
}
|
||||
|
||||
return null;
|
||||
@@ -60,11 +71,20 @@ namespace BinaryObjectScanner.Packer
|
||||
return false;
|
||||
|
||||
// Only process the overlay if it has an archive signature
|
||||
if (!overlayData.StartsWith(SabreTools.Models.PKZIP.Constants.LocalFileHeaderSignatureBytes))
|
||||
string extension = string.Empty;
|
||||
if (overlayData.StartsWith([0x37, 0x7A, 0xBC, 0xAF, 0x27, 0x1C]))
|
||||
extension = "7z";
|
||||
else if (overlayData.StartsWith(SabreTools.Models.PKZIP.Constants.LocalFileHeaderSignatureBytes))
|
||||
extension = "zip";
|
||||
else if (overlayData.StartsWith([0x52, 0x61, 0x72, 0x21, 0x1A, 0x07, 0x00]))
|
||||
extension = "rar";
|
||||
else if (overlayData.StartsWith([0x52, 0x61, 0x72, 0x21, 0x1A, 0x07, 0x01, 0x00]))
|
||||
extension = "rar";
|
||||
else
|
||||
return false;
|
||||
|
||||
// Create the temp filename
|
||||
string tempFile = $"embedded_overlay.zip";
|
||||
string tempFile = $"embedded_overlay.{extension}";
|
||||
tempFile = Path.Combine(outDir, tempFile);
|
||||
var directoryName = Path.GetDirectoryName(tempFile);
|
||||
if (directoryName != null && !Directory.Exists(directoryName))
|
||||
@@ -100,13 +120,24 @@ namespace BinaryObjectScanner.Packer
|
||||
{
|
||||
if (value == null || value is not byte[] ba)
|
||||
continue;
|
||||
if (!ba.StartsWith(SabreTools.Models.PKZIP.Constants.LocalFileHeaderSignatureBytes))
|
||||
|
||||
// Only process the resource if it has an archive signature
|
||||
string extension = string.Empty;
|
||||
if (ba.StartsWith([0x37, 0x7A, 0xBC, 0xAF, 0x27, 0x1C]))
|
||||
extension = "7z";
|
||||
else if (ba.StartsWith(SabreTools.Models.PKZIP.Constants.LocalFileHeaderSignatureBytes))
|
||||
extension = "zip";
|
||||
else if (ba.StartsWith([0x52, 0x61, 0x72, 0x21, 0x1A, 0x07, 0x00]))
|
||||
extension = "rar";
|
||||
else if (ba.StartsWith([0x52, 0x61, 0x72, 0x21, 0x1A, 0x07, 0x01, 0x00]))
|
||||
extension = "rar";
|
||||
else
|
||||
continue;
|
||||
|
||||
try
|
||||
{
|
||||
// Create the temp filename
|
||||
string tempFile = $"embedded_resource_{i++}.zip";
|
||||
string tempFile = $"embedded_resource_{i++}.{extension}";
|
||||
tempFile = Path.Combine(outDir, tempFile);
|
||||
var directoryName = Path.GetDirectoryName(tempFile);
|
||||
if (directoryName != null && !Directory.Exists(directoryName))
|
||||
|
||||
@@ -88,87 +88,8 @@ namespace BinaryObjectScanner.Packer
|
||||
{
|
||||
try
|
||||
{
|
||||
// Get the matching PE format
|
||||
var format = GetPEFormat(pex);
|
||||
if (format == null)
|
||||
return false;
|
||||
|
||||
// Get the overlay data for easier reading
|
||||
int overlayOffset = 0, dataStart = 0;
|
||||
var overlayData = pex.OverlayData;
|
||||
if (overlayData == null)
|
||||
return false;
|
||||
|
||||
// Skip over the additional DLL name, if we expect it
|
||||
if (format.Dll)
|
||||
{
|
||||
// Read the name length
|
||||
byte dllNameLength = overlayData.ReadByte(ref overlayOffset);
|
||||
dataStart++;
|
||||
|
||||
// Read the name, if it exists
|
||||
if (dllNameLength != 0)
|
||||
{
|
||||
// Ignore the name for now
|
||||
_ = overlayData.ReadBytes(ref overlayOffset, dllNameLength);
|
||||
dataStart += dllNameLength;
|
||||
|
||||
// Named DLLs also have a DLL length that we ignore
|
||||
_ = overlayData.ReadUInt32(ref overlayOffset);
|
||||
dataStart += 4;
|
||||
}
|
||||
}
|
||||
|
||||
// Check if flags are consistent
|
||||
if (!format.NoCrc)
|
||||
{
|
||||
// Unlike WiseUnpacker, we ignore the flag value here
|
||||
_ = overlayData.ReadUInt32(ref overlayOffset);
|
||||
}
|
||||
|
||||
// Ensure that we have an archive end
|
||||
if (format.ArchiveEnd > 0)
|
||||
{
|
||||
overlayOffset = (int)(dataStart + format.ArchiveEnd);
|
||||
int archiveEndLoaded = overlayData.ReadInt32(ref overlayOffset);
|
||||
if (archiveEndLoaded != 0)
|
||||
format.ArchiveEnd = archiveEndLoaded;
|
||||
}
|
||||
|
||||
// Skip to the start of the archive
|
||||
overlayOffset = (int)(dataStart + format.ArchiveStart);
|
||||
|
||||
// Skip over the initialization text, if we expect it
|
||||
if (format.InitText)
|
||||
{
|
||||
int initTextLength = overlayData.ReadByte(ref overlayOffset);
|
||||
_ = overlayData.ReadBytes(ref overlayOffset, initTextLength);
|
||||
}
|
||||
|
||||
// Cache the current offset in the overlay as the "start of data"
|
||||
int offsetReal = overlayOffset;
|
||||
|
||||
// If the first entry is PKZIP, we assume it's an embedded zipfile
|
||||
var magic = overlayData.ReadBytes(ref overlayOffset, 4); overlayOffset -= 4;
|
||||
bool pkzip = magic?.StartsWith(new byte?[] { (byte)'P', (byte)'K' }) ?? false;
|
||||
|
||||
// Create the output directory
|
||||
Directory.CreateDirectory(outDir);
|
||||
|
||||
// If we have PKZIP
|
||||
if (pkzip)
|
||||
{
|
||||
string tempFile = Path.Combine(outDir, "WISEDATA.zip");
|
||||
using Stream tempStream = File.Open(tempFile, FileMode.Create, FileAccess.Write, FileShare.ReadWrite);
|
||||
tempStream.Write(overlayData, overlayOffset, overlayData.Length - overlayOffset);
|
||||
return true;
|
||||
}
|
||||
|
||||
// If we have DEFLATE -- TODO: Port implementation here or use DeflateStream
|
||||
else
|
||||
{
|
||||
return Extractor.ExtractTo(file, outDir);
|
||||
}
|
||||
return Extractor.ExtractTo(file, outDir);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
|
||||
@@ -102,12 +102,19 @@ namespace BinaryObjectScanner.Protection
|
||||
if (name.OptionalEquals("SafeDisc", StringComparison.OrdinalIgnoreCase))
|
||||
return "SafeDisc";
|
||||
|
||||
// Found in Redump entries 20729 and 65569.
|
||||
// Get the debug data
|
||||
if (pex.FindCodeViewDebugTableByPath("SafeDisc").Count > 0)
|
||||
return "SafeDisc";
|
||||
if (pex.FindCodeViewDebugTableByPath("Safedisk").Count > 0)
|
||||
return "SafeDisc";
|
||||
try
|
||||
{
|
||||
// Found in Redump entries 20729 and 65569.
|
||||
// Get the debug data
|
||||
if (pex.FindCodeViewDebugTableByPath("SafeDisc").Count > 0)
|
||||
return "SafeDisc";
|
||||
if (pex.FindCodeViewDebugTableByPath("Safedisk").Count > 0)
|
||||
return "SafeDisc";
|
||||
}
|
||||
catch
|
||||
{
|
||||
// Absorb inconsistent debug data errors
|
||||
}
|
||||
|
||||
// TODO: Investigate various section names:
|
||||
// "STLPORT_" - Found in Redump entry 11638.
|
||||
|
||||
@@ -171,7 +171,7 @@ namespace BinaryObjectScanner.Protection
|
||||
if (cDilla != null)
|
||||
results.AddRange(cDilla);
|
||||
|
||||
// Run C-Dilla directory checks
|
||||
// Run FLEXnet directory checks
|
||||
var flexNet = FLEXNetCheckDirectoryPath(path, files);
|
||||
if (flexNet != null)
|
||||
results.AddRange(flexNet);
|
||||
@@ -550,28 +550,70 @@ namespace BinaryObjectScanner.Protection
|
||||
// Found in Redump entry 66005.
|
||||
"1.00.025"
|
||||
|
||||
// Source not documented.
|
||||
// Found in Redump entries 1882, 30049, 34828, 35922, 38212, 84280, and 97611.
|
||||
or "1.00.026"
|
||||
|
||||
// Found in Redump entries 31575 and 41923.
|
||||
or "1.00.030"
|
||||
|
||||
// Found in Redump entries 1883 and 42114.
|
||||
or "1.00.032"
|
||||
|
||||
// Found in Redump entries 36223 and 40770.
|
||||
or "1.00.035"
|
||||
|
||||
// Found in Redump entries 42155 and 47574.
|
||||
or "1.01.034"
|
||||
|
||||
// Found in Redump entry 51459.
|
||||
or "1.01.038"
|
||||
|
||||
// Found in Redump entries 34562 and 63304.
|
||||
or "1.01.043"
|
||||
|
||||
// Found in Redump entries 61731 and 81619.
|
||||
or "1.01.044"
|
||||
|
||||
// Found in Redump entries 29073 and 31149.
|
||||
or "1.06.000"
|
||||
|
||||
// Found in Redump entries 9718 and 46756.
|
||||
or "1.07.000"
|
||||
|
||||
// Found in Redump entries 12885 and 66210.
|
||||
or "1.09.000"
|
||||
|
||||
// Found in Redump entries 3569, 3570, 37523, 66586.
|
||||
or "1.11.000"
|
||||
|
||||
// Found in Redump entries 21154, 37982, 108632.
|
||||
or "1.20.000"
|
||||
|
||||
// Found in Redump entries 17024/37920.
|
||||
or "1.20.001"
|
||||
|
||||
// Found in Redump entries 28708, 31526, 43321, 55080, 75501.
|
||||
or "1.30.010"
|
||||
|
||||
// Found in Redump entries 9617 and 49552.
|
||||
or "1.35.000"
|
||||
|
||||
// Found in Redump entries 2595 and 30121.
|
||||
or "1.40.004"
|
||||
|
||||
// Found in Redump entries 1887, 44350, 61047, and 63323.
|
||||
or "1.41.000"
|
||||
|
||||
// Found in Redump entries 37832 and 42091.
|
||||
or "1.41.001"
|
||||
|
||||
// Found in Redump entries 30555 and 55078.
|
||||
or "1.45.011"
|
||||
|
||||
// Found in Redump entries 28810 and 62935.
|
||||
or "1.50.020"
|
||||
|
||||
// Source not documented.
|
||||
or "2.05.030"
|
||||
or "2.10.030"
|
||||
or "2.30.030"
|
||||
|
||||
@@ -21,13 +21,17 @@ namespace BinaryObjectScanner
|
||||
/// </summary>
|
||||
/// <param name="key">Key to add information to</param>
|
||||
/// <param name="value">String value to add</param>
|
||||
public void Append(string key, string value)
|
||||
public void Append(string key, string? value)
|
||||
{
|
||||
// If the value is empty, don't add it
|
||||
if (value == null || value.Trim().Length == 0)
|
||||
return;
|
||||
|
||||
Append(key, [value]);
|
||||
EnsureKey(key);
|
||||
foreach (string subValue in ProcessProtectionString(value))
|
||||
{
|
||||
this[key].Enqueue(subValue);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -37,9 +41,6 @@ namespace BinaryObjectScanner
|
||||
/// <param name="values">String value array to add</param>
|
||||
public void Append(string key, string[] values)
|
||||
{
|
||||
// Use a placeholder value if the key is null
|
||||
key ??= "NO FILENAME";
|
||||
|
||||
// Add the key if needed and then append the lists
|
||||
EnsureKey(key);
|
||||
foreach (string value in values)
|
||||
@@ -47,7 +48,10 @@ namespace BinaryObjectScanner
|
||||
if (value == null || value.Trim().Length == 0)
|
||||
continue;
|
||||
|
||||
this[key].Enqueue(value);
|
||||
foreach (string subValue in ProcessProtectionString(value))
|
||||
{
|
||||
this[key].Enqueue(subValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -181,15 +185,49 @@ namespace BinaryObjectScanner
|
||||
if (values == null)
|
||||
return;
|
||||
|
||||
EnsureKey(key);
|
||||
foreach (string value in values)
|
||||
{
|
||||
if (value == null || value.Trim().Length == 0)
|
||||
continue;
|
||||
|
||||
this[key].Enqueue(value);
|
||||
foreach (string subValue in ProcessProtectionString(value))
|
||||
{
|
||||
this[key].Enqueue(subValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#region Helpers
|
||||
|
||||
/// <summary>
|
||||
/// Process a protection string if it includes multiple protections
|
||||
/// </summary>
|
||||
/// <param name="protection">Protection string to process</param>
|
||||
/// <returns>Set of protections parsed, empty on error</returns>
|
||||
internal static List<string> ProcessProtectionString(string? protection)
|
||||
{
|
||||
// If we have an invalid protection string
|
||||
if (string.IsNullOrEmpty(protection))
|
||||
return [];
|
||||
|
||||
// Setup the output queue
|
||||
var protections = new List<string>();
|
||||
|
||||
// If we have an indicator of multiple protections
|
||||
if (protection!.Contains(";"))
|
||||
{
|
||||
var splitProtections = protection.Split(';');
|
||||
protections.AddRange(splitProtections);
|
||||
}
|
||||
else
|
||||
{
|
||||
protections.Add(protection);
|
||||
}
|
||||
|
||||
return protections;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Ensure the collection for the given key exists
|
||||
/// </summary>
|
||||
@@ -202,5 +240,7 @@ namespace BinaryObjectScanner
|
||||
TryAdd(key, new ConcurrentQueue<string>());
|
||||
#endif
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -284,7 +284,7 @@ namespace BinaryObjectScanner
|
||||
else
|
||||
{
|
||||
var subProtection = detectable.Detect(stream, fileName, _options.IncludeDebug);
|
||||
protections.Append(fileName, ProcessProtectionString(subProtection));
|
||||
protections.Append(fileName, subProtection);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -395,8 +395,8 @@ namespace BinaryObjectScanner
|
||||
if (File.Exists(path))
|
||||
{
|
||||
var protection = impl.CheckFilePath(path!);
|
||||
var subProtections = ProcessProtectionString(protection);
|
||||
protections.AddRange(subProtections);
|
||||
if (protection != null)
|
||||
protections.Add(protection);
|
||||
}
|
||||
|
||||
// If we have a directory path
|
||||
@@ -411,37 +411,5 @@ namespace BinaryObjectScanner
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Helpers
|
||||
|
||||
/// <summary>
|
||||
/// Process a protection string if it includes multiple protections
|
||||
/// </summary>
|
||||
/// <param name="protection">Protection string to process</param>
|
||||
/// <returns>Set of protections parsed, empty on error</returns>
|
||||
internal static List<string> ProcessProtectionString(string? protection)
|
||||
{
|
||||
// If we have an invalid protection string
|
||||
if (string.IsNullOrEmpty(protection))
|
||||
return [];
|
||||
|
||||
// Setup the output queue
|
||||
var protections = new List<string>();
|
||||
|
||||
// If we have an indicator of multiple protections
|
||||
if (protection!.Contains(";"))
|
||||
{
|
||||
var splitProtections = protection.Split(';');
|
||||
protections.AddRange(splitProtections);
|
||||
}
|
||||
else
|
||||
{
|
||||
protections.Add(protection);
|
||||
}
|
||||
|
||||
return protections;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
<Nullable>enable</Nullable>
|
||||
<SuppressTfmSupportBuildWarnings>true</SuppressTfmSupportBuildWarnings>
|
||||
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
|
||||
<Version>3.3.0</Version>
|
||||
<Version>3.3.1</Version>
|
||||
</PropertyGroup>
|
||||
|
||||
<!-- Support All Frameworks -->
|
||||
@@ -37,7 +37,7 @@
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="SabreTools.IO" Version="1.6.1" />
|
||||
<PackageReference Include="SabreTools.Serialization" Version="1.8.0" />
|
||||
<PackageReference Include="SabreTools.Serialization" Version="1.8.1" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
@@ -9,7 +9,7 @@
|
||||
<Nullable>enable</Nullable>
|
||||
<SuppressTfmSupportBuildWarnings>true</SuppressTfmSupportBuildWarnings>
|
||||
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
|
||||
<Version>3.3.0</Version>
|
||||
<Version>3.3.1</Version>
|
||||
</PropertyGroup>
|
||||
|
||||
<!-- Support All Frameworks -->
|
||||
|
||||
Reference in New Issue
Block a user