mirror of
https://github.com/SabreTools/BinaryObjectScanner.git
synced 2026-07-08 18:06:34 +00:00
Move Crunch to its own Packer, improve SmartE detection. (#353)
* Move Crunch to its own Packer, improve SmartE detection. * Fix formatting by removing brackets Co-authored-by: Matt Nadareski <mnadareski@outlook.com> * Remove named section checks, minor formatting fixes * Add newline before summary. * Remove empty returns. * Remove unnecessary newline * Change Crunch to use IExtractableExecutable * Remove unnecessary whitespace. * Add tests for Crunch. --------- Co-authored-by: Matt Nadareski <mnadareski@outlook.com>
This commit is contained in:
committed by
GitHub
parent
63a5a25a17
commit
9fee74f2a6
36
BinaryObjectScanner.Test/Packer/CrunchTests.cs
Normal file
36
BinaryObjectScanner.Test/Packer/CrunchTests.cs
Normal file
@@ -0,0 +1,36 @@
|
||||
using System.IO;
|
||||
using BinaryObjectScanner.Packer;
|
||||
using Xunit;
|
||||
|
||||
namespace BinaryObjectScanner.Test.Packer
|
||||
{
|
||||
public class CrunchTests
|
||||
{
|
||||
[Fact]
|
||||
public void CheckPortableExecutableTest()
|
||||
{
|
||||
string file = "filename";
|
||||
SabreTools.Models.PortableExecutable.Executable model = new();
|
||||
Stream source = new MemoryStream();
|
||||
SabreTools.Serialization.Wrappers.PortableExecutable pex = new(model, source);
|
||||
|
||||
var checker = new Crunch();
|
||||
string? actual = checker.CheckExecutable(file, pex, includeDebug: false);
|
||||
Assert.Null(actual);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ExtractPortableExecutableTest()
|
||||
{
|
||||
string file = "filename";
|
||||
SabreTools.Models.PortableExecutable.Executable model = new();
|
||||
Stream source = new MemoryStream();
|
||||
SabreTools.Serialization.Wrappers.PortableExecutable pex = new(model, source);
|
||||
string outputDir = string.Empty;
|
||||
|
||||
var checker = new Crunch();
|
||||
bool actual = checker.Extract(file, pex, outputDir, includeDebug: false);
|
||||
Assert.False(actual);
|
||||
}
|
||||
}
|
||||
}
|
||||
32
BinaryObjectScanner/Packer/Crunch.cs
Normal file
32
BinaryObjectScanner/Packer/Crunch.cs
Normal file
@@ -0,0 +1,32 @@
|
||||
using BinaryObjectScanner.Interfaces;
|
||||
using SabreTools.Serialization.Wrappers;
|
||||
|
||||
namespace BinaryObjectScanner.Packer
|
||||
{
|
||||
// Packer used by all known SmartE games, but also used by some other non-SmartE protected software as well.
|
||||
// https://web.archive.org/web/20020806102129/http://www.bit-arts.com/windows_solutions.html
|
||||
// TODO: Other BitArts products may also use this same string. No samples have yet been found.
|
||||
public class Crunch : IExtractableExecutable<PortableExecutable>
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
public string? CheckExecutable(string file, PortableExecutable pex, bool includeDebug)
|
||||
{
|
||||
// Get the last section strings, if they exist
|
||||
var sections = pex.Model.SectionTable ?? [];
|
||||
var strs = pex.GetSectionStrings(sections.Length - 1);
|
||||
if (strs != null)
|
||||
{
|
||||
if (strs.Exists(s => s.Contains("BITARTS")))
|
||||
return "Crunch";
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public bool Extract(string file, PortableExecutable pex, string outDir, bool includeDebug)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,26 +1,45 @@
|
||||
using System.Collections.Generic;
|
||||
using BinaryObjectScanner.Interfaces;
|
||||
using SabreTools.Matching;
|
||||
using SabreTools.Matching.Content;
|
||||
using SabreTools.Matching.Paths;
|
||||
using SabreTools.Serialization.Wrappers;
|
||||
|
||||
namespace BinaryObjectScanner.Protection
|
||||
{
|
||||
public class SmartE : IExecutableCheck<PortableExecutable>, IPathCheck
|
||||
public class SmartE : IPathCheck, IExecutableCheck<PortableExecutable>
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
public string? CheckExecutable(string file, PortableExecutable pex, bool includeDebug)
|
||||
{
|
||||
// Get the last section strings, if they exist
|
||||
var sections = pex.Model.SectionTable ?? [];
|
||||
var strs = pex.GetSectionStrings(sections.Length - 1);
|
||||
if (strs != null)
|
||||
{
|
||||
if (strs.Exists(s => s.Contains("BITARTS")))
|
||||
return "SmartE";
|
||||
}
|
||||
// Only works on stub generated from running the program yourself
|
||||
if (pex.InternalName.OptionalEquals("SmarteSECURE"))
|
||||
return "SmartE";
|
||||
|
||||
var sections = pex.Model.SectionTable ?? [];
|
||||
|
||||
return null;
|
||||
if (sections.Length > 0)
|
||||
{
|
||||
// Get the last section data, if it exists
|
||||
var lastSectionData = pex.GetSectionData(sections.Length - 1);
|
||||
if (lastSectionData != null)
|
||||
{
|
||||
// All sections seen so far are the last sections, so this is "technically"
|
||||
// the only known needed check so far. Others kept as backups if this fails
|
||||
// on some future entry
|
||||
var matchers = GenerateMatchers();
|
||||
var match = MatchUtil.GetFirstMatch(file, lastSectionData, matchers, includeDebug);
|
||||
if (!string.IsNullOrEmpty(match))
|
||||
return match;
|
||||
}
|
||||
}
|
||||
|
||||
// Specific known named sections:
|
||||
// .bss (Rise of Nations)
|
||||
// .tls (Zoo Tycoon 2)
|
||||
// .idata (http://redump.org/disc/58561/ and http://redump.org/disc/71983/)
|
||||
// .edata (http://redump.org/disc/36619/)
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
@@ -49,5 +68,31 @@ namespace BinaryObjectScanner.Protection
|
||||
|
||||
return MatchUtil.GetFirstMatch(path, matchers, any: true);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Generate the set of matchers used for each section
|
||||
/// </summary>
|
||||
private static List<ContentMatchSet> GenerateMatchers()
|
||||
{
|
||||
return
|
||||
[
|
||||
// Matches most games, but a few like http://redump.org/disc/16541/
|
||||
// are only matched on the 00001/2.TMP files. PiD and other programs
|
||||
// don't detect this game either, though (Aside from the stub)
|
||||
new(new byte?[]
|
||||
{
|
||||
0xEB, 0x15, 0x03, 0x00, 0x00, 0x00, null, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x68, 0x00, 0x00, 0x00, 0x00, 0x55,
|
||||
0xE8, 0x00, 0x00, 0x00, 0x00, 0x5D, 0x81, 0xED,
|
||||
0x1D, 0x00, 0x00, 0x00, 0x8B, 0xC5, 0x55, 0x60,
|
||||
0x9C, 0x2B, 0x85, 0x8F, 0x07, 0x00, 0x00, 0x89,
|
||||
0x85, 0x83, 0x07, 0x00, 0x00, 0xFF, 0x74, 0x24,
|
||||
0x2C, 0xE8, 0xBB, 0x01, 0x00, 0x00, 0x0F, 0x82,
|
||||
0x2F, 0x06, 0x00, 0x00, 0xE8, 0x8E, 0x04, 0x00,
|
||||
0x00, 0x49, 0x0F, 0x88, 0x23, 0x06
|
||||
}, "SmartE"),
|
||||
];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user