mirror of
https://github.com/SabreTools/BinaryObjectScanner.git
synced 2026-07-08 18:06:34 +00:00
More incidental cleanup
This commit is contained in:
@@ -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
|
||||
};
|
||||
];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -29,17 +29,17 @@ namespace BinaryObjectScanner.Packer
|
||||
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))
|
||||
@@ -64,14 +64,11 @@ namespace BinaryObjectScanner.Packer
|
||||
if (payload == null || payload.Length == 0)
|
||||
return false;
|
||||
|
||||
// Determine which compression was used
|
||||
bool zlib = pex.FindResourceByNamedType("99, 1").Count > 0;
|
||||
|
||||
// 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
|
||||
{
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)";
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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)";
|
||||
}
|
||||
|
||||
@@ -648,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
|
||||
@@ -672,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
|
||||
@@ -715,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
|
||||
|
||||
@@ -188,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)
|
||||
@@ -245,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
|
||||
|
||||
@@ -13,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/>
|
||||
|
||||
@@ -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";
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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/>
|
||||
@@ -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,14 +167,12 @@ 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;
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,21 +32,15 @@ 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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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,199 +66,201 @@ 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;
|
||||
}
|
||||
|
||||
@@ -76,64 +76,61 @@ namespace BinaryObjectScanner.Protection
|
||||
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;
|
||||
|
||||
@@ -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";
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
@@ -164,35 +166,11 @@ namespace BinaryObjectScanner.Protection
|
||||
if (!sectionContent.FirstPosition(check, out int position))
|
||||
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})";
|
||||
}
|
||||
@@ -203,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)
|
||||
@@ -214,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]))
|
||||
|
||||
@@ -34,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".
|
||||
|
||||
@@ -60,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;
|
||||
@@ -132,7 +132,7 @@ namespace BinaryObjectScanner.Protection
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="Interfaces.IPathCheck.CheckDirectoryPath(string, List{string})"/>
|
||||
internal List<string> CDillaCheckDirectoryPath(string path, List<string>? files)
|
||||
internal static List<string> CDillaCheckDirectoryPath(string path, List<string>? files)
|
||||
{
|
||||
var matchers = new List<PathMatchSet>
|
||||
{
|
||||
@@ -175,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>
|
||||
{
|
||||
|
||||
@@ -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;
|
||||
@@ -62,7 +62,7 @@ namespace BinaryObjectScanner.Protection
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="Interfaces.IPathCheck.CheckDirectoryPath(string, List{string})"/>
|
||||
internal List<string> CactusDataShieldCheckDirectoryPath(string path, List<string>? files)
|
||||
internal static List<string> CactusDataShieldCheckDirectoryPath(string path, List<string>? files)
|
||||
{
|
||||
// TODO: Verify if these are OR or AND
|
||||
var matchers = new List<PathMatchSet>
|
||||
@@ -89,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>
|
||||
{
|
||||
|
||||
@@ -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;
|
||||
@@ -68,7 +68,7 @@ namespace BinaryObjectScanner.Protection
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="Interfaces.IPathCheck.CheckDirectoryPath(string, List{string})"/>
|
||||
internal List<string> FLEXNetCheckDirectoryPath(string path, List<string>? files)
|
||||
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>
|
||||
{
|
||||
|
||||
@@ -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, List{string})"/>
|
||||
internal List<string> RipGuardCheckDirectoryPath(string path, List<string>? files)
|
||||
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>
|
||||
{
|
||||
|
||||
@@ -40,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)
|
||||
@@ -67,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;
|
||||
@@ -147,7 +147,7 @@ namespace BinaryObjectScanner.Protection
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="Interfaces.IPathCheck.CheckDirectoryPath(string, List{string})"/>
|
||||
internal List<string> SafeCastCheckDirectoryPath(string path, List<string>? files)
|
||||
internal static List<string> SafeCastCheckDirectoryPath(string path, List<string>? files)
|
||||
{
|
||||
var matchers = new List<PathMatchSet>
|
||||
{
|
||||
@@ -190,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>
|
||||
{
|
||||
|
||||
@@ -41,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;
|
||||
@@ -49,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");
|
||||
@@ -103,14 +109,10 @@ namespace BinaryObjectScanner.Protection
|
||||
|
||||
// Found in Redump entries 20729 and 65569.
|
||||
// Get the debug data
|
||||
try
|
||||
{
|
||||
if (pex.FindCodeViewDebugTableByPath("SafeDisc").Count > 0)
|
||||
return "SafeDisc";
|
||||
if (pex.FindCodeViewDebugTableByPath("Safedisk").Count > 0)
|
||||
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.
|
||||
@@ -126,7 +128,7 @@ namespace BinaryObjectScanner.Protection
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="Interfaces.IPathCheck.CheckDirectoryPath(string, List{string})"/>
|
||||
internal List<string> SafeDiscCheckDirectoryPath(string path, List<string>? files)
|
||||
internal static List<string> SafeDiscCheckDirectoryPath(string path, List<string>? files)
|
||||
{
|
||||
var matchers = new List<PathMatchSet>
|
||||
{
|
||||
@@ -264,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>
|
||||
{
|
||||
@@ -927,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;
|
||||
|
||||
@@ -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
|
||||
@@ -249,7 +239,7 @@ namespace BinaryObjectScanner.Protection
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="IPathCheck.CheckDirectoryPath(string, List{string})"/>
|
||||
internal List<string> MacrovisionCheckDirectoryPath(string path, List<string>? files)
|
||||
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>
|
||||
{
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -89,8 +89,7 @@ namespace BinaryObjectScanner.Protection
|
||||
}
|
||||
|
||||
// Get the .vob.pcd section, if it exists
|
||||
bool vobpcdSection = pex.ContainsSection(".vob.pcd", exact: true);
|
||||
if (vobpcdSection)
|
||||
if (pex.ContainsSection(".vob.pcd", exact: true))
|
||||
return "VOB ProtectCD";
|
||||
|
||||
return null;
|
||||
@@ -217,16 +216,22 @@ namespace BinaryObjectScanner.Protection
|
||||
|
||||
int index = positions[0] + 37;
|
||||
byte subversion = fileContent[index];
|
||||
|
||||
index += 2;
|
||||
byte version = fileContent[index];
|
||||
|
||||
index = positions[0] + 49;
|
||||
int irefBuild = BitConverter.ToInt32(fileContent, index);
|
||||
|
||||
index = positions[0] + 53;
|
||||
byte versionindicatorPD9 = fileContent[index];
|
||||
|
||||
index = positions[0] + 0x40;
|
||||
byte subsubversionPD9x = fileContent[index];
|
||||
|
||||
index++;
|
||||
byte subversionPD9x2 = fileContent[index];
|
||||
|
||||
index++;
|
||||
byte subversionPD9x1 = fileContent[index];
|
||||
|
||||
@@ -308,10 +313,11 @@ namespace BinaryObjectScanner.Protection
|
||||
// TODO: Ensure that this version finding works for all known versions
|
||||
private static string GetVOBVersion(byte[] fileContent, int position)
|
||||
{
|
||||
byte version = fileContent[position - 2];
|
||||
byte subVersion = (byte)((fileContent[position - 3] & 0xF0) >> 4);
|
||||
byte subSubVersion = (byte)((fileContent[position - 4] & 0xF0) >> 4);
|
||||
return $"{version}.{subVersion}.{subSubVersion}";
|
||||
byte major = fileContent[position - 2];
|
||||
byte minor = (byte)((fileContent[position - 3] & 0xF0) >> 4);
|
||||
byte patch = (byte)((fileContent[position - 4] & 0xF0) >> 4);
|
||||
|
||||
return $"{major}.{minor}.{patch}";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,23 +13,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>
|
||||
// (char)0x00 + Allocator + (char)0x00 + (char)0x00 + (char)0x00 + (char)0x00
|
||||
new(new byte?[]
|
||||
{
|
||||
// (char)0x00 + Allocator + (char)0x00 + (char)0x00 + (char)0x00 + (char)0x00
|
||||
new(new byte?[]
|
||||
{
|
||||
0x00, 0x41, 0x6C, 0x6C, 0x6F, 0x63, 0x61, 0x74,
|
||||
0x6F, 0x72, 0x00, 0x00, 0x00, 0x00
|
||||
}, "Ring PROTECH / ProRing [Check disc for physical ring] (Unconfirmed - Please report to us on Github)"),
|
||||
};
|
||||
0x00, 0x41, 0x6C, 0x6C, 0x6F, 0x63, 0x61, 0x74,
|
||||
0x6F, 0x72, 0x00, 0x00, 0x00, 0x00
|
||||
}, "Ring PROTECH / ProRing [Check disc for physical ring] (Unconfirmed - Please report to us on Github)"),
|
||||
};
|
||||
|
||||
return MatchUtil.GetFirstMatch(file, fileContent, contentMatchSets, includeDebug);
|
||||
}
|
||||
|
||||
return null;
|
||||
return MatchUtil.GetFirstMatch(file, fileContent, contentMatchSets, includeDebug);
|
||||
}
|
||||
|
||||
// TODO: Confirm if these checks are only for ProRing or if they are also for older Ring PROTECH
|
||||
|
||||
@@ -82,8 +82,7 @@ namespace BinaryObjectScanner.Protection
|
||||
|
||||
// Get the .svkp section, if it exists.
|
||||
// This section is present in at least versions 1.05-1.32, but isn't present in every known sample of these versions. Removing this section name may be a perk of the licensed version.
|
||||
bool neolitSection = pex.ContainsSection(".svkp", exact: true);
|
||||
if (neolitSection)
|
||||
if (pex.ContainsSection(".svkp", exact: true))
|
||||
return "SVKP";
|
||||
|
||||
return null;
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using BinaryObjectScanner.Interfaces;
|
||||
using SabreTools.Matching;
|
||||
@@ -41,22 +40,18 @@ namespace BinaryObjectScanner.Protection
|
||||
return $"SecuROM Product Activation v{pex.GetInternalVersion()}";
|
||||
|
||||
// Get the matrosch section, if it exists
|
||||
bool matroschSection = pex.ContainsSection("matrosch", exact: true);
|
||||
if (matroschSection)
|
||||
if (pex.ContainsSection("matrosch", exact: true))
|
||||
return $"SecuROM Matroschka Package";
|
||||
|
||||
bool dsstextSection = pex.ContainsSection(".dsstext", exact: true);
|
||||
if (dsstextSection)
|
||||
if (pex.ContainsSection(".dsstext", exact: true))
|
||||
return $"SecuROM 8.03.03+";
|
||||
|
||||
// Get the .securom section, if it exists
|
||||
bool securomSection = pex.ContainsSection(".securom", exact: true);
|
||||
if (securomSection)
|
||||
if (pex.ContainsSection(".securom", exact: true))
|
||||
return $"SecuROM {GetV7Version(pex)}";
|
||||
|
||||
// Get the .sll section, if it exists
|
||||
bool sllSection = pex.ContainsSection(".sll", exact: true);
|
||||
if (sllSection)
|
||||
if (pex.ContainsSection(".sll", exact: true))
|
||||
return $"SecuROM SLL Protected (for SecuROM v8.x)";
|
||||
|
||||
// Search after the last section
|
||||
@@ -73,7 +68,7 @@ namespace BinaryObjectScanner.Protection
|
||||
if (nthSection == null)
|
||||
continue;
|
||||
|
||||
string nthSectionName = Encoding.UTF8.GetString(nthSection.Name ?? []).TrimEnd('\0');
|
||||
string nthSectionName = Encoding.ASCII.GetString(nthSection.Name ?? []).TrimEnd('\0');
|
||||
if (nthSectionName != ".idata" && nthSectionName != ".rsrc")
|
||||
{
|
||||
var nthSectionData = pex.GetFirstSectionData(nthSectionName);
|
||||
@@ -104,9 +99,7 @@ namespace BinaryObjectScanner.Protection
|
||||
}
|
||||
|
||||
// Get the .cms_d and .cms_t sections, if they exist -- TODO: Confirm if both are needed or either/or is fine
|
||||
bool cmsdSection = pex.ContainsSection(".cmd_d", true);
|
||||
bool cmstSection = pex.ContainsSection(".cms_t", true);
|
||||
if (cmsdSection || cmstSection)
|
||||
if (pex.ContainsSection(".cmd_d", true) || pex.ContainsSection(".cms_t", true))
|
||||
return $"SecuROM 1-3";
|
||||
|
||||
return null;
|
||||
|
||||
@@ -62,7 +62,7 @@ namespace BinaryObjectScanner.Protection
|
||||
|
||||
// Found in "TafseerVer4.exe" in IA item "TAFSEERVER4SETUP"
|
||||
var strings = pex.GetFirstSectionStrings(".section") ?? [];
|
||||
if (strings.Exists(s => s?.Contains("SOFTLOCKPROTECTION") == true))
|
||||
if (strings.Exists(s => s.Contains("SOFTLOCKPROTECTION")))
|
||||
return "SoftLock";
|
||||
|
||||
// Investigate if the ".section" section is an indicator of SoftLock
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using BinaryObjectScanner.Interfaces;
|
||||
using SabreTools.Matching;
|
||||
using SabreTools.Matching.Content;
|
||||
@@ -77,7 +76,7 @@ namespace BinaryObjectScanner.Protection
|
||||
return "SolidShield EXE Wrapper v1";
|
||||
|
||||
// Search the last two available sections
|
||||
for (int i = (pex.SectionNames != null && pex.SectionNames.Length >= 2 ? pex.SectionNames.Length - 2 : 0); i < (pex.SectionNames?.Length ?? 0); i++)
|
||||
for (int i = Math.Max(sections.Length - 2, 0); i < sections.Length; i++)
|
||||
{
|
||||
// Get the nth section strings, if they exist
|
||||
var strs = pex.GetSectionStrings(i);
|
||||
@@ -152,23 +151,18 @@ namespace BinaryObjectScanner.Protection
|
||||
|
||||
int position = positions[0];
|
||||
|
||||
#if NET20 || NET35 || NET40
|
||||
byte[] id1 = new byte[3];
|
||||
Array.Copy(fileContent, position + 5, id1, 0, 3);
|
||||
byte[] id2 = new byte[4];
|
||||
Array.Copy(fileContent, position + 16, id2, 0, 3);
|
||||
#else
|
||||
var id1 = new ArraySegment<byte>(fileContent, position + 5, 3);
|
||||
var id2 = new ArraySegment<byte>(fileContent, position + 16, 4);
|
||||
#endif
|
||||
|
||||
if (id1.SequenceEqual(new byte[] { 0x00, 0x00, 0x00 })
|
||||
&& id2.SequenceEqual(new byte[] { 0x00, 0x10, 0x00, 0x00 }))
|
||||
if (id1[0] == 0x00 && id1[1] == 0x00 && id1[2] == 0x00
|
||||
&& id2[0] == 0x00 && id2[1] == 0x10 && id2[2] == 0x00 && id2[3] == 0x00)
|
||||
{
|
||||
return "v1";
|
||||
}
|
||||
else if (id1.SequenceEqual(new byte[] { 0x2E, 0x6F, 0x26 })
|
||||
&& id2.SequenceEqual(new byte[] { 0xDB, 0xC5, 0x20, 0x3A })) // [0xDB, 0xC5, 0x20, 0x3A, 0xB9]
|
||||
else if (id1[0] == 0x2E && id1[1] == 0x6F && id1[2] == 0x26
|
||||
&& id2[0] == 0xDB && id2[1] == 0xC5 && id2[2] == 0x20 && id2[3] == 0x3A) // [0xDB, 0xC5, 0x20, 0x3A, 0xB9]
|
||||
{
|
||||
return "v2"; // TODO: Verify against other SolidShield 2 discs
|
||||
}
|
||||
@@ -183,24 +177,20 @@ namespace BinaryObjectScanner.Protection
|
||||
return null;
|
||||
|
||||
int position = positions[0];
|
||||
#if NET20 || NET35 || NET40
|
||||
|
||||
byte[] id1 = new byte[3];
|
||||
Array.Copy(fileContent, position + 4, id1, 0, 3);
|
||||
byte[] id2 = new byte[4];
|
||||
Array.Copy(fileContent, position + 15, id2, 0, 3);
|
||||
#else
|
||||
var id1 = new ArraySegment<byte>(fileContent, position + 4, 3);
|
||||
var id2 = new ArraySegment<byte>(fileContent, position + 15, 4);
|
||||
#endif
|
||||
|
||||
if ((fileContent[position + 3] == 0x04 || fileContent[position + 3] == 0x05)
|
||||
&& id1.SequenceEqual(new byte[] { 0x00, 0x00, 0x00 })
|
||||
&& id2.SequenceEqual(new byte[] { 0x00, 0x10, 0x00, 0x00 }))
|
||||
&& id1[0] == 0x00 && id1[1] == 0x00 && id1[2] == 0x00
|
||||
&& id2[0] == 0x00 && id2[1] == 0x10 && id2[2] == 0x00 && id2[3] == 0x00)
|
||||
{
|
||||
return "2 (SolidShield v2 EXE Wrapper)";
|
||||
}
|
||||
else if (id1.SequenceEqual(new byte[] { 0x00, 0x00, 0x00 })
|
||||
&& id2.SequenceEqual(new byte[] { 0x00, 0x00, 0x00, 0x00 }))
|
||||
else if (id1[0] == 0x00 && id1[1] == 0x00 && id1[2] == 0x00
|
||||
&& id2[0] == 0x00 && id2[1] == 0x10 && id2[2] == 0x00 && id2[3] == 0x00)
|
||||
{
|
||||
// "T" + (char)0x00 + "a" + (char)0x00 + "g" + (char)0x00 + "e" + (char)0x00 + "s" + (char)0x00 + "S" + (char)0x00 + "e" + (char)0x00 + "t" + (char)0x00 + "u" + (char)0x00 + "p" + (char)0x00 + (char)0x00 + (char)0x00 + (char)0x00 + (char)0x00 + "0" + (char)0x00 + (char)0x8 + (char)0x00 + (char)0x1 + (char)0x0 + "F" + (char)0x00 + "i" + (char)0x00 + "l" + (char)0x00 + "e" + (char)0x00 + "V" + (char)0x00 + "e" + (char)0x00 + "r" + (char)0x00 + "s" + (char)0x00 + "i" + (char)0x00 + "o" + (char)0x00 + "n" + (char)0x00 + (char)0x00 + (char)0x00 + (char)0x00
|
||||
byte?[] check2 =
|
||||
|
||||
@@ -90,13 +90,11 @@ namespace BinaryObjectScanner.Protection
|
||||
// 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)
|
||||
if (pex.ContainsSection(".brick", exact: true))
|
||||
return "StarForce 3-5";
|
||||
|
||||
// Get the .sforce* section, if it exists
|
||||
bool sforceSection = pex.ContainsSection(".sforce", exact: false);
|
||||
if (sforceSection)
|
||||
if (pex.ContainsSection(".sforce", exact: false))
|
||||
return "StarForce 3-5";
|
||||
|
||||
return null;
|
||||
|
||||
@@ -17,21 +17,21 @@ namespace BinaryObjectScanner.Protection
|
||||
return null;
|
||||
|
||||
var name = pex.FileDescription;
|
||||
if (!string.IsNullOrEmpty(name) && name!.Contains("Steam Autorun Setup"))
|
||||
if (name?.Contains("Steam Autorun Setup") == true)
|
||||
return "Steam";
|
||||
else if (!string.IsNullOrEmpty(name) && name!.Contains("Steam Client API"))
|
||||
else if (name?.Contains("Steam Client API") == true)
|
||||
return "Steam";
|
||||
else if (!string.IsNullOrEmpty(name) && name!.Contains("Steam Client Engine"))
|
||||
else if (name?.Contains("Steam Client Engine") == true)
|
||||
return $"Steam Client Engine {pex.GetInternalVersion()}";
|
||||
else if (!string.IsNullOrEmpty(name) && name!.Contains("Steam Client Service"))
|
||||
else if (name?.Contains("Steam Client Service") == true)
|
||||
return "Steam";
|
||||
|
||||
name = pex.ProductName;
|
||||
if (!string.IsNullOrEmpty(name) && name!.Contains("Steam Autorun Setup"))
|
||||
if (name?.Contains("Steam Autorun Setup") == true)
|
||||
return "Steam";
|
||||
else if (!string.IsNullOrEmpty(name) && name!.Contains("Steam Client API"))
|
||||
else if (name?.Contains("Steam Client API") == true)
|
||||
return "Steam";
|
||||
else if (!string.IsNullOrEmpty(name) && name!.Contains("Steam Client Service"))
|
||||
else if (name?.Contains("Steam Client Service") == true)
|
||||
return "Steam";
|
||||
|
||||
/// TODO: Add entry point checks
|
||||
|
||||
@@ -51,7 +51,11 @@ namespace BinaryObjectScanner.Protection
|
||||
var matchers = new List<ContentMatchSet>
|
||||
{
|
||||
// (char)0xE8 + u + (char)0x00 + (char)0x00 + (char)0x00 + (char)0xE8 + ?? + ?? + (char)0xFF + (char)0xFF + "h"
|
||||
new(new byte?[] { 0xE8, 0x75, 0x00, 0x00, 0x00, 0xE8, null, null, 0xFF, 0xFF, 0x68 }, GetVersion, "TAGES"),
|
||||
new(new byte?[]
|
||||
{
|
||||
0xE8, 0x75, 0x00, 0x00, 0x00, 0xE8, null, null,
|
||||
0xFF, 0xFF, 0x68
|
||||
}, GetVersion, "TAGES"),
|
||||
};
|
||||
|
||||
var match = MatchUtil.GetFirstMatch(file, dataSectionRaw, matchers, includeDebug);
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
using System.Collections.Generic;
|
||||
using BinaryObjectScanner.Interfaces;
|
||||
using BinaryObjectScanner.Interfaces;
|
||||
using SabreTools.Serialization.Wrappers;
|
||||
|
||||
namespace BinaryObjectScanner.Protection
|
||||
@@ -33,7 +32,7 @@ namespace BinaryObjectScanner.Protection
|
||||
return null;
|
||||
|
||||
// Get the "Arcsoft " section strings, if they exist
|
||||
List<string>? strs = pex.GetFirstSectionStrings("Arcsoft ");
|
||||
var strs = pex.GetFirstSectionStrings("Arcsoft ");
|
||||
if (strs != null)
|
||||
{
|
||||
// Found in "uDigital Theatre.exe" in http://downloads.fyxm.net/ArcSoft-TotalMedia-23085.html (https://web.archive.org/web/20221114042838/http://files.fyxm.net/23/23085/totalmediatheatre3platinum_retail_tbyb_all.exe).
|
||||
|
||||
@@ -18,26 +18,26 @@ namespace BinaryObjectScanner.Protection
|
||||
return null;
|
||||
|
||||
var name = pex.FileDescription;
|
||||
if (!string.IsNullOrEmpty(name) && name!.Contains("Ubisoft Connect Installer"))
|
||||
if (name?.Contains("Ubisoft Connect Installer") == true)
|
||||
return "Uplay / Ubisoft Connect";
|
||||
else if (!string.IsNullOrEmpty(name) && name!.Contains("Ubisoft Connect Service"))
|
||||
else if (name?.Contains("Ubisoft Connect Service") == true)
|
||||
return "Uplay / Ubisoft Connect";
|
||||
else if (!string.IsNullOrEmpty(name) && name!.Contains("Ubisoft Connect WebCore"))
|
||||
else if (name?.Contains("Ubisoft Connect WebCore") == true)
|
||||
return "Uplay / Ubisoft Connect";
|
||||
else if (!string.IsNullOrEmpty(name) && name!.Contains("Ubisoft Crash Reporter"))
|
||||
else if (name?.Contains("Ubisoft Crash Reporter") == true)
|
||||
return "Uplay / Ubisoft Connect";
|
||||
else if (!string.IsNullOrEmpty(name) && name!.Contains("Ubisoft Game Launcher"))
|
||||
else if (name?.Contains("Ubisoft Game Launcher") == true)
|
||||
return "Uplay / Ubisoft Connect";
|
||||
else if (!string.IsNullOrEmpty(name) && name!.Contains("Ubisoft Uplay Installer"))
|
||||
else if (name?.Contains("Ubisoft Uplay Installer") == true)
|
||||
return "Uplay / Ubisoft Connect";
|
||||
else if (!string.IsNullOrEmpty(name) && name!.Contains("Uplay launcher"))
|
||||
else if (name?.Contains("Uplay launcher") == true)
|
||||
return "Uplay / Ubisoft Connect";
|
||||
|
||||
// There's also a variant that looks like "Uplay <version> installer"
|
||||
name = pex.ProductName;
|
||||
if (!string.IsNullOrEmpty(name) && name!.Contains("Ubisoft Connect"))
|
||||
if (name?.Contains("Ubisoft Connect") == true)
|
||||
return "Uplay / Ubisoft Connect";
|
||||
else if (!string.IsNullOrEmpty(name) && name!.Contains("Uplay"))
|
||||
else if (name?.Contains("Uplay") == true)
|
||||
return "Uplay / Ubisoft Connect";
|
||||
|
||||
return null;
|
||||
|
||||
Reference in New Issue
Block a user