mirror of
https://github.com/SabreTools/BinaryObjectScanner.git
synced 2026-09-22 14:54:56 +00:00
Why is there so much StarForce, geez (#180)
* Begin work on overhauling StarForce detection, and to add notes. * Attempt to add SFFS file detection. * Fix minor TAGES issue.
This commit is contained in:
committed by
GitHub
parent
9c173fd3a1
commit
56c27d0b8f
@@ -80,6 +80,11 @@
|
||||
/// </summary>
|
||||
SevenZip,
|
||||
|
||||
/// <summary>
|
||||
/// StarForce FileSystem file
|
||||
/// </summary>
|
||||
SFFS,
|
||||
|
||||
/// <summary>
|
||||
/// Tape archive
|
||||
/// </summary>
|
||||
|
||||
49
BurnOutSharp/FileType/SFFS.cs
Normal file
49
BurnOutSharp/FileType/SFFS.cs
Normal file
@@ -0,0 +1,49 @@
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.IO;
|
||||
using BurnOutSharp.Interfaces;
|
||||
using BurnOutSharp.Tools;
|
||||
|
||||
namespace BurnOutSharp.FileType
|
||||
{
|
||||
/// <summary>
|
||||
/// StarForce Filesystem file
|
||||
/// </summary>
|
||||
public class SFFS : IScannable
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
public ConcurrentDictionary<string, ConcurrentQueue<string>> Scan(Scanner scanner, string file)
|
||||
{
|
||||
if (!File.Exists(file))
|
||||
return null;
|
||||
|
||||
using (var fs = File.OpenRead(file))
|
||||
{
|
||||
return Scan(scanner, fs, file);
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public ConcurrentDictionary<string, ConcurrentQueue<string>> Scan(Scanner scanner, Stream stream, string file)
|
||||
{
|
||||
var protections = new ConcurrentDictionary<string, ConcurrentQueue<string>>();
|
||||
try
|
||||
{
|
||||
byte[] magic = new byte[16];
|
||||
stream.Read(magic, 0, 16);
|
||||
|
||||
if (Utilities.GetFileType(magic) == SupportedFileType.SFFS)
|
||||
{
|
||||
Utilities.AppendToDictionary(protections, file, "StarForce Filesystem Container");
|
||||
return protections;
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
if (scanner.IncludeDebug) Console.WriteLine(ex);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3,6 +3,7 @@ using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using BurnOutSharp.Interfaces;
|
||||
using BurnOutSharp.Matching;
|
||||
using BurnOutSharp.Tools;
|
||||
using BurnOutSharp.Wrappers;
|
||||
|
||||
@@ -10,6 +11,13 @@ namespace BurnOutSharp.ProtectionType
|
||||
{
|
||||
public class StarForce : IPathCheck, IPortableExecutableCheck
|
||||
{
|
||||
// TODO: Bring up to par with PiD.
|
||||
// Known issues:
|
||||
// "Game.exe" not detected, "SF Crypto" not found in protect.* files (Redump entry 96137).
|
||||
// "HR.exe" Themida not detected, doesn't detect "[Builder]" (Is that the default StarForce?) (Redump entry 94805).
|
||||
// "ChromeEngine3.dll" and "SGP4.dll" not detected, doesn't detect "[FL Disc]" (Redump entry 93098).
|
||||
// "Replay.exe" not detected, doesn't detect "[FL Disc]" (Redump entry 81756).
|
||||
// Doesn't detect "[Pro]" (Redump entry 91336).
|
||||
/// <inheritdoc/>
|
||||
public string CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug)
|
||||
{
|
||||
@@ -24,12 +32,26 @@ namespace BurnOutSharp.ProtectionType
|
||||
else if (name?.Contains("Protection Technology") == true) // Protection Technology (StarForce)?
|
||||
return $"StarForce {Utilities.GetInternalVersion(pex)}";
|
||||
|
||||
// TODO: Decide if internal name checks are safe to use.
|
||||
name = pex.InternalName;
|
||||
if (name?.Equals("CORE.EXE", StringComparison.Ordinal) == true)
|
||||
return $"StarForce {Utilities.GetInternalVersion(pex)}";
|
||||
else if (name?.Equals("protect.exe", StringComparison.Ordinal) == true)
|
||||
|
||||
// Found in "protect.x64" and "protect.x86" in Redump entry 94805.
|
||||
if (name?.Equals("CORE.ADMIN", StringComparison.Ordinal) == true)
|
||||
return $"StarForce {Utilities.GetInternalVersion(pex)}";
|
||||
|
||||
|
||||
// These checks currently disabled due being possibly too generic:
|
||||
// Found in "protect.dll" in Redump entry 94805.
|
||||
// if (name?.Equals("CORE.DLL", StringComparison.Ordinal) == true)
|
||||
// return $"StarForce {Utilities.GetInternalVersion(pex)}";
|
||||
//
|
||||
// Found in "protect.exe" in Redump entry 94805.
|
||||
// if (name?.Equals("CORE.EXE", StringComparison.Ordinal) == true)
|
||||
// return $"StarForce {Utilities.GetInternalVersion(pex)}";
|
||||
//
|
||||
// else if (name?.Equals("protect.exe", StringComparison.Ordinal) == true)
|
||||
// return $"StarForce {Utilities.GetInternalVersion(pex)}";
|
||||
|
||||
// Check the export name table
|
||||
if (pex.ExportNameTable != null)
|
||||
{
|
||||
@@ -40,6 +62,25 @@ namespace BurnOutSharp.ProtectionType
|
||||
|
||||
// TODO: Find what fvinfo field actually maps to this
|
||||
name = pex.FileDescription;
|
||||
|
||||
// There are some File Description checks that are currently too generic to use.
|
||||
// "Host Library" - Found in "protect.dll" in Redump entry 81756.
|
||||
// "User Interface Application" - Found in "protect.exe" in Redump entry 81756.
|
||||
// "Helper Application" - Found in "protect.x64" and "protect.x86" in Redump entry 81756.
|
||||
|
||||
// Found in "protect.exe" in Redump entry 94805.
|
||||
if (name?.Contains("FrontLine Protection GUI Application") == true)
|
||||
return $"StarForce {Utilities.GetInternalVersion(pex)}";
|
||||
|
||||
// Found in "protect.dll" in Redump entry 94805.
|
||||
if (name?.Contains("FrontLine Protection Library") == true)
|
||||
return $"StarForce {Utilities.GetInternalVersion(pex)}";
|
||||
|
||||
// Found in "protect.x64" and "protect.x86" in Redump entry 94805.
|
||||
if (name?.Contains("FrontLine Helper") == true)
|
||||
return $"StarForce {Utilities.GetInternalVersion(pex)}";
|
||||
|
||||
// TODO: Find a sample of this check.
|
||||
if (name?.Contains("Protected Module") == true)
|
||||
return $"StarForce 5";
|
||||
|
||||
@@ -62,30 +103,43 @@ namespace BurnOutSharp.ProtectionType
|
||||
/// <inheritdoc/>
|
||||
public ConcurrentQueue<string> CheckDirectoryPath(string path, IEnumerable<string> files)
|
||||
{
|
||||
// These have too high of a chance of over-matching by themselves
|
||||
// var matchers = new List<PathMatchSet>
|
||||
// {
|
||||
// // TODO: Re-consolidate these once path matching is improved
|
||||
// new PathMatchSet(new PathMatch("/protect.dll", useEndsWith: true), "StarForce"),
|
||||
// new PathMatchSet(new PathMatch("/protect.exe", useEndsWith: true), "StarForce"),
|
||||
// };
|
||||
var matchers = new List<PathMatchSet>
|
||||
{
|
||||
// This file combination is found in Redump entry 21136.
|
||||
new PathMatchSet(new List<PathMatch>
|
||||
{
|
||||
new PathMatch("protect.x86", useEndsWith: true),
|
||||
new PathMatch("protect.x64", useEndsWith: true),
|
||||
new PathMatch("protect.dll", useEndsWith: true),
|
||||
new PathMatch("protect.exe", useEndsWith: true),
|
||||
new PathMatch("protect.msg", useEndsWith: true),
|
||||
}, "StarForce"),
|
||||
|
||||
// return MatchUtil.GetAllMatches(files, matchers, any: false);
|
||||
return null;
|
||||
// This file combination is found in multiple games, such as Redump entries 81756, 91336, and 93657.
|
||||
new PathMatchSet(new List<PathMatch>
|
||||
{
|
||||
new PathMatch("protect.x86", useEndsWith: true),
|
||||
new PathMatch("protect.x64", useEndsWith: true),
|
||||
new PathMatch("protect.dll", useEndsWith: true),
|
||||
new PathMatch("protect.exe", useEndsWith: true),
|
||||
}, "StarForce"),
|
||||
|
||||
// This file combination is found in Redump entry 96137.
|
||||
new PathMatchSet(new List<PathMatch>
|
||||
{
|
||||
new PathMatch("protect.x86", useEndsWith: true),
|
||||
new PathMatch("protect.dll", useEndsWith: true),
|
||||
new PathMatch("protect.exe", useEndsWith: true),
|
||||
}, "StarForce"),
|
||||
};
|
||||
|
||||
return MatchUtil.GetAllMatches(files, matchers, any: false);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public string CheckFilePath(string path)
|
||||
{
|
||||
// These have too high of a chance of over-matching by themselves
|
||||
// var matchers = new List<PathMatchSet>
|
||||
// {
|
||||
// // TODO: Re-consolidate these once path matching is improved
|
||||
// new PathMatchSet(new PathMatch("/protect.dll", useEndsWith: true), "StarForce"),
|
||||
// new PathMatchSet(new PathMatch("/protect.exe", useEndsWith: true), "StarForce"),
|
||||
// };
|
||||
|
||||
// return MatchUtil.GetFirstMatch(path, matchers, any: true);
|
||||
// TODO: Determine if there are any file name checks that aren't too generic to use on their own.
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -151,7 +151,7 @@ namespace BurnOutSharp.ProtectionType
|
||||
new PathMatchSet(new PathMatch("GAME.KWN", useEndsWith: true), "TAGES (BASIC?)"),
|
||||
};
|
||||
|
||||
return MatchUtil.GetAllMatches(files, matchers, any: true);
|
||||
return MatchUtil.GetAllMatches(files, matchers, any: false);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
|
||||
@@ -339,6 +339,13 @@ namespace BurnOutSharp
|
||||
Utilities.AppendToDictionary(protections, subProtections);
|
||||
}
|
||||
|
||||
// SFFS
|
||||
if (scannable is SFFS)
|
||||
{
|
||||
var subProtections = scannable.Scan(this, stream, fileName);
|
||||
Utilities.AppendToDictionary(protections, subProtections);
|
||||
}
|
||||
|
||||
// Text-based files
|
||||
if (scannable is Textfile)
|
||||
{
|
||||
|
||||
@@ -327,6 +327,14 @@ namespace BurnOutSharp.Tools
|
||||
|
||||
#endregion
|
||||
|
||||
#region SFFS
|
||||
|
||||
// Found in Redump entry 81756, confirmed to be "StarForce Filesystem" by PiD.
|
||||
if (magic.StartsWith(new byte?[] { 0x53, 0x46, 0x46, 0x53, 0x01, 0x00, 0x00, 0x00 }))
|
||||
return SupportedFileType.SFFS;
|
||||
|
||||
#endregion
|
||||
|
||||
#region SevenZip
|
||||
|
||||
if (magic.StartsWith(new byte?[] { 0x37, 0x7a, 0xbc, 0xaf, 0x27, 0x1c }))
|
||||
|
||||
Reference in New Issue
Block a user