Files
BinaryObjectScanner/BinaryObjectScanner.Protection/StarForce.cs
Matt Nadareski e118418a23 Move protection scans to their own library
This change also removes a couple of things from `BurnOutSharp.Tools.Utilities` that are no longer needed there. Linear executables are included in the scanning classes. Update the guides accordingly.
2023-03-09 23:19:27 -05:00

146 lines
6.6 KiB
C#

using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using BinaryObjectScanner.Interfaces;
using BinaryObjectScanner.Matching;
using BinaryObjectScanner.Wrappers;
namespace BinaryObjectScanner.Protection
{
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)
{
// Get the sections from the executable, if possible
var sections = pex?.SectionTable;
if (sections == null)
return null;
string name = pex.LegalCopyright;
if (name?.StartsWith("(c) Protection Technology") == true) // (c) Protection Technology (StarForce)?
return $"StarForce {pex.GetInternalVersion()}";
else if (name?.Contains("Protection Technology") == true) // Protection Technology (StarForce)?
return $"StarForce {pex.GetInternalVersion()}";
// TODO: Decide if internal name checks are safe to use.
name = pex.InternalName;
// Found in "protect.x64" and "protect.x86" in Redump entry 94805.
if (name?.Equals("CORE.ADMIN", StringComparison.Ordinal) == true)
return $"StarForce {pex.GetInternalVersion()}";
// 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 {Tools.Utilities.GetInternalVersion(pex)}";
//
// Found in "protect.exe" in Redump entry 94805.
// if (name?.Equals("CORE.EXE", StringComparison.Ordinal) == true)
// return $"StarForce {Tools.Utilities.GetInternalVersion(pex)}";
//
// else if (name?.Equals("protect.exe", StringComparison.Ordinal) == true)
// return $"StarForce {Tools.Utilities.GetInternalVersion(pex)}";
// Check the export name table
if (pex.ExportNameTable != null)
{
// TODO: Should we just check for "PSA_*" instead of a single entry?
if (pex.ExportNameTable.Any(s => s == "PSA_GetDiscLabel"))
return $"StarForce {pex.GetInternalVersion()}";
}
// 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 {pex.GetInternalVersion()}";
// Found in "protect.dll" in Redump entry 94805.
if (name?.Contains("FrontLine Protection Library") == true)
return $"StarForce {pex.GetInternalVersion()}";
// Found in "protect.x64" and "protect.x86" in Redump entry 94805.
if (name?.Contains("FrontLine Helper") == true)
return $"StarForce {pex.GetInternalVersion()}";
// TODO: Find a sample of this check.
if (name?.Contains("Protected Module") == true)
return $"StarForce 5";
// TODO: Check to see if there are any missing checks
// https://github.com/horsicq/Detect-It-Easy/blob/master/db/PE/StarForce.2.sg
// Get the .brick section, if it exists
bool brickSection = pex.ContainsSection(".brick", exact: true);
if (brickSection)
return "StarForce 3-5";
// Get the .sforce* section, if it exists
bool sforceSection = pex.ContainsSection(".sforce", exact: false);
if (sforceSection)
return "StarForce 3-5";
return null;
}
/// <inheritdoc/>
public ConcurrentQueue<string> CheckDirectoryPath(string path, IEnumerable<string> files)
{
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"),
// 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)
{
// TODO: Determine if there are any file name checks that aren't too generic to use on their own.
return null;
}
}
}