Compare commits

...

11 Commits
2.0.0 ... 2.1.0

Author SHA1 Message Date
Matt Nadareski
d6feab3958 Bump version to 2.1.0 2022-04-17 22:02:43 -07:00
Matt Nadareski
2d2207a1ee Update UnshieldSharp to 1.6.8 2022-04-17 13:35:14 -07:00
Matt Nadareski
89b86630d8 Update WiseUnpacker to 1.0.3 2022-04-17 13:33:59 -07:00
Matt Nadareski
bcb1571a23 Use .NET Standard 2.0, add .NET 6.0 2022-04-16 21:58:54 -07:00
Matt Nadareski
5d658ebe4a Upgrade to VS2022 for AppVeyor 2022-04-16 21:56:45 -07:00
Matt Nadareski
7d2de80e77 Fix over-matching SafeLock 2022-04-02 21:36:29 -07:00
Matt Nadareski
b933249ff7 Add resource finding on creation 2022-04-02 16:12:23 -07:00
Matt Nadareski
61c09e3c97 Move resource helpers to PortableExecutable 2022-04-02 15:54:51 -07:00
SilasLaspada
32695ee6dd Add support for detecting AutoPlay Media Studio (#116)
* Add support for detecting AutoPlay Media Studio

* Comment out too vague AutoPlay Media Studio check

* Tweak comment
2022-04-01 23:23:32 -07:00
Matt Nadareski
4b66cd8cd2 Update file version resource handling 2022-04-01 10:16:31 -07:00
SilasLaspada
edc4cc1706 Refactor Setup Factory detection (#115)
* Refactor Setup Factory detection

* Address Setup Factory PR comments

* Fix whitespace
2022-04-01 09:58:02 -07:00
33 changed files with 555 additions and 449 deletions

View File

@@ -1,14 +1,15 @@
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 16
VisualStudioVersion = 16.0.29306.81
# Visual Studio Version 17
VisualStudioVersion = 17.1.32407.343
MinimumVisualStudioVersion = 10.0.40219.1
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BurnOutSharp", "BurnOutSharp\BurnOutSharp.csproj", "{1DA4212E-6071-4951-B45D-BB74A7838246}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Test", "Test\Test.csproj", "{88735BA2-778D-4192-8EB2-FFF6843719E2}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Test", "Test\Test.csproj", "{88735BA2-778D-4192-8EB2-FFF6843719E2}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{68D10531-99CB-40B1-8912-73FA286C9433}"
ProjectSection(SolutionItems) = preProject
appveyor.yml = appveyor.yml
LICENSE = LICENSE
README.md = README.md
EndProjectSection
@@ -17,7 +18,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "WixToolset", "WixToolset",
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{182E02A8-5E8E-4140-9C9B-61049C33E921}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WixToolset.Dtf.WindowsInstaller", "WixToolset\src\WixToolset.Dtf.WindowsInstaller\WixToolset.Dtf.WindowsInstaller.csproj", "{B3537EB7-CEF6-4D90-A041-47626442A656}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WixToolset.Dtf.WindowsInstaller", "WixToolset\src\WixToolset.Dtf.WindowsInstaller\WixToolset.Dtf.WindowsInstaller.csproj", "{B3537EB7-CEF6-4D90-A041-47626442A656}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
@@ -41,11 +42,11 @@ Global
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {0B343DD2-8852-47B0-9647-DFCFBEDF933C}
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
{182E02A8-5E8E-4140-9C9B-61049C33E921} = {09D405CA-CF15-4929-8408-C970F0656C62}
{B3537EB7-CEF6-4D90-A041-47626442A656} = {182E02A8-5E8E-4140-9C9B-61049C33E921}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {0B343DD2-8852-47B0-9647-DFCFBEDF933C}
EndGlobalSection
EndGlobal

View File

@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>net48;netcoreapp3.1;net5.0</TargetFrameworks>
<TargetFrameworks>netstandard2.0</TargetFrameworks>
<PlatformTarget>x86</PlatformTarget>
<Title>BurnOutSharp</Title>
<AssemblyName>BurnOutSharp</AssemblyName>
@@ -11,9 +11,9 @@
<Copyright>Copyright (c)2005-2010 Gernot Knippen, Copyright (c)2018-2022 Matt Nadareski</Copyright>
<PackageLicenseFile>LICENSE.txt</PackageLicenseFile>
<RepositoryUrl>https://github.com/mnadareski/BurnOutSharp</RepositoryUrl>
<Version>2.0.0</Version>
<AssemblyVersion>2.0.0</AssemblyVersion>
<FileVersion>2.0.0</FileVersion>
<Version>2.1.0</Version>
<AssemblyVersion>2.1.0</AssemblyVersion>
<FileVersion>2.1.0</FileVersion>
<IncludeSource>true</IncludeSource>
<IncludeSymbols>true</IncludeSymbols>
</PropertyGroup>
@@ -23,14 +23,14 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="SharpCompress" Version="0.30.1" />
<PackageReference Include="SharpCompress" Version="0.31.0" />
<PackageReference Include="System.Text.Encoding.CodePages" Version="6.0.0" />
<PackageReference Include="Teronis.MSBuild.Packaging.ProjectBuildInPackage" Version="1.0.0">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
<PackageReference Include="UnshieldSharp" Version="1.6.7" />
<PackageReference Include="WiseUnpacker" Version="1.0.2" />
<PackageReference Include="UnshieldSharp" Version="1.6.8" />
<PackageReference Include="WiseUnpacker" Version="1.0.3" />
</ItemGroup>
<!-- These are needed for dealing with submodules -->

View File

@@ -1,9 +1,13 @@
using System;
using System.IO;
using System.Linq;
using System.Xml;
using BurnOutSharp.ExecutableType.Microsoft.MZ.Headers;
using BurnOutSharp.ExecutableType.Microsoft.PE.Entries;
using BurnOutSharp.ExecutableType.Microsoft.PE.Headers;
using BurnOutSharp.ExecutableType.Microsoft.PE.Sections;
using BurnOutSharp.ExecutableType.Microsoft.PE.Tables;
using BurnOutSharp.ExecutableType.Microsoft.Resources;
using BurnOutSharp.Tools;
namespace BurnOutSharp.ExecutableType.Microsoft.PE
@@ -180,6 +184,60 @@ namespace BurnOutSharp.ExecutableType.Microsoft.PE
#endregion
#region Resources
/// <summary>
/// Company name resource string
/// </summary>
public string CompanyName { get; private set; }
/// <summary>
/// File description resource string
/// </summary>
public string FileDescription { get; private set; }
/// <summary>
/// File version resource string
/// </summary>
public string FileVersion { get; private set; }
/// <summary>
/// Internal name resource string
/// </summary>
public string InternalName { get; private set; }
/// <summary>
/// Legal copyright resource string
/// </summary>
public string LegalCopyright { get; private set; }
/// <summary>
/// Description manifest string
/// </summary>
public string ManifestDescription { get; private set; }
/// <summary>
/// Version manifest string
/// </summary>
public string ManifestVersion { get; private set; }
/// <summary>
/// Original filename resource string
/// </summary>
public string OriginalFileName { get; private set; }
/// <summary>
/// Product name resource string
/// </summary>
public string ProductName { get; private set; }
/// <summary>
/// Product version resource string
/// </summary>
public string ProductVersion { get; private set; }
#endregion
#region Constructors
/// <summary>
@@ -307,6 +365,9 @@ namespace BurnOutSharp.ExecutableType.Microsoft.PE
this.TextSectionRaw = this.ReadRawSection(".text", force: true, first: false);
#endregion
// Populate resources, if possible
PopulateResourceStrings();
}
catch (Exception ex)
{
@@ -414,6 +475,9 @@ namespace BurnOutSharp.ExecutableType.Microsoft.PE
this.TextSectionRaw = this.ReadRawSection(".text", force: true, first: false);
#endregion
// Populate resources, if possible
PopulateResourceStrings();
}
catch (Exception ex)
{
@@ -426,7 +490,258 @@ namespace BurnOutSharp.ExecutableType.Microsoft.PE
#endregion
#region Helpers
#region Resource Helpers
/// <summary>
/// Find resource data in a ResourceSection, if possible
/// </summary>
/// <param name="dataStart">String to use if checking for data starting with a string</param>
/// <param name="dataContains">String to use if checking for data contains a string</param>
/// <param name="dataEnd">String to use if checking for data ending with a string</param>
/// <returns>Full encoded resource data, null on error</returns>
public ResourceDataEntry FindResource(string dataStart = null, string dataContains = null, string dataEnd = null)
{
if (this.ResourceSection == null)
return null;
return FindResourceInTable(this.ResourceSection.ResourceDirectoryTable, dataStart, dataContains, dataEnd);
}
/// <summary>
/// Get the assembly identity node from an embedded manifest
/// </summary>
/// <param name="manifestString">String representing the XML document</param>
/// <returns>Assembly identity node, if possible</returns>
private XmlElement GetAssemblyNode(string manifestString)
{
// An invalid string means we can't read it
if (string.IsNullOrWhiteSpace(manifestString))
return null;
try
{
// Load the XML string as a document
var manifestDoc = new XmlDocument();
manifestDoc.LoadXml(manifestString);
// If the XML has no children, it's invalid
if (!manifestDoc.HasChildNodes)
return null;
// Try to read the assembly node
return manifestDoc["assembly"];
}
catch (Exception ex)
{
return null;
}
}
/// <summary>
/// Find the assembly manifest from a resource section, if possible
/// </summary>
/// <returns>Full assembly manifest, null on error</returns>
private string FindAssemblyManifest() => FindResource(dataContains: "<assembly")?.DataAsUTF8String;
/// <summary>
/// Find resource data in a ResourceDirectoryTable, if possible
/// </summary>
/// <param name="rdt">ResourceDirectoryTable representing a layer</param>
/// <param name="dataStart">String to use if checking for data starting with a string</param>
/// <param name="dataContains">String to use if checking for data contains a string</param>
/// <param name="dataEnd">String to use if checking for data ending with a string</param>
/// <returns>Full encoded resource data, null on error</returns>
private ResourceDataEntry FindResourceInTable(ResourceDirectoryTable rdt, string dataStart, string dataContains, string dataEnd)
{
if (rdt == null)
return null;
try
{
foreach (var rdte in rdt.NamedEntries)
{
if (rdte.IsResourceDataEntry() && rdte.DataEntry != null)
{
if (dataStart != null && rdte.DataEntry.DataAsUTF8String.StartsWith(dataStart))
return rdte.DataEntry;
else if (dataContains != null && rdte.DataEntry.DataAsUTF8String.Contains(dataContains))
return rdte.DataEntry;
else if (dataEnd != null && rdte.DataEntry.DataAsUTF8String.EndsWith(dataStart))
return rdte.DataEntry;
}
else
{
var manifest = FindResourceInTable(rdte.Subdirectory, dataStart, dataContains, dataEnd);
if (manifest != null)
return manifest;
}
}
foreach (var rdte in rdt.IdEntries)
{
if (rdte.IsResourceDataEntry() && rdte.DataEntry != null)
{
if (dataStart != null && rdte.DataEntry.DataAsUTF8String.StartsWith(dataStart))
return rdte.DataEntry;
else if (dataContains != null && rdte.DataEntry.DataAsUTF8String.Contains(dataContains))
return rdte.DataEntry;
else if (dataEnd != null && rdte.DataEntry.DataAsUTF8String.EndsWith(dataStart))
return rdte.DataEntry;
}
else
{
var manifest = FindResourceInTable(rdte.Subdirectory, dataStart, dataContains, dataEnd);
if (manifest != null)
return manifest;
}
}
}
catch { }
return null;
}
/// <summary>
/// Get the assembly version as determined by an embedded assembly manifest
/// </summary>
/// <returns>Description string, null on error</returns>
private string GetManifestDescription()
{
// If we don't have a complete PE executable, just return null
if (this.ResourceSection == null)
return null;
// Read in the manifest to a string
string manifestString = FindAssemblyManifest();
if (string.IsNullOrWhiteSpace(manifestString))
return null;
// Try to read the XML in from the string
try
{
// Try to read the assembly
var assemblyNode = GetAssemblyNode(manifestString);
if (assemblyNode == null)
return null;
// Return the content of the description node, if possible
var descriptionNode = assemblyNode["description"];
if (descriptionNode == null)
return null;
return descriptionNode.InnerXml;
}
catch
{
return null;
}
}
/// <summary>
/// Get the assembly version as determined by an embedded assembly manifest
/// </summary>
/// <returns>Version string, null on error</returns>
private string GetManifestVersion()
{
// If we don't have a complete PE executable, just return null
if (this.ResourceSection == null)
return null;
// Read in the manifest to a string
string manifestString = FindAssemblyManifest();
if (string.IsNullOrWhiteSpace(manifestString))
return null;
// Try to read the XML in from the string
try
{
// Try to read the assembly
var assemblyNode = GetAssemblyNode(manifestString);
if (assemblyNode == null)
return null;
// Try to read the assemblyIdentity
var assemblyIdentityNode = assemblyNode["assemblyIdentity"];
if (assemblyIdentityNode == null)
return null;
// Return the version attribute, if possible
return assemblyIdentityNode.GetAttribute("version");
}
catch
{
return null;
}
}
/// <summary>
/// Get a resource string from the version info
/// </summary>
/// <returns>Original filename string, null on error</returns>
private string GetResourceString(string key)
{
var resourceStrings = GetVersionInfo()?.ChildrenStringFileInfo?.Children?.Children;
if (resourceStrings == null)
return null;
var value = resourceStrings.FirstOrDefault(s => s.Key == key);
if (!string.IsNullOrWhiteSpace(value?.Value))
return value.Value.Trim(' ', '\0');
return null;
}
/// <summary>
/// Get the version info object related to file contents, if possible
/// </summary>
/// <returns>VersionInfo object on success, null on error</returns>
private VersionInfo GetVersionInfo()
{
// If we don't have a complete PE executable, just return null
if (this.ResourceSection == null)
return null;
// Try to get the matching resource
var resource = FindResource(dataContains: "V\0S\0_\0V\0E\0R\0S\0I\0O\0N\0_\0I\0N\0F\0O\0");
if (resource?.Data == null)
return null;
try
{
int index = 0;
return VersionInfo.Deserialize(resource.Data, ref index);
}
catch (Exception ex)
{
// Console.WriteLine(ex);
return null;
}
}
/// <summary>
/// Populate all resource strings
/// </summary>
private void PopulateResourceStrings()
{
// Standalone resource strings
this.CompanyName = GetResourceString("CompanyName");
this.FileDescription = GetResourceString("FileDescription");
this.FileVersion = GetResourceString("FileVersion")?.Replace(", ", ".");
this.InternalName = GetResourceString("InternalName");
this.LegalCopyright = GetResourceString("LegalCopyright");
this.OriginalFileName = GetResourceString("OriginalFileName");
this.ProductName = GetResourceString("ProductName");
this.ProductVersion = GetResourceString("ProductVersion")?.Replace(", ", ".");
// TODO: Make these combined calls more efficient
// Manifest resource strings
this.ManifestDescription = GetManifestDescription();
this.ManifestVersion = GetManifestVersion();
}
#endregion
#region Section Helpers
/// <summary>
/// Determine if a section is contained within the section table

View File

@@ -0,0 +1,72 @@
using System;
using System.Collections.Concurrent;
using System.IO;
using BurnOutSharp.ExecutableType.Microsoft.PE;
using BurnOutSharp.Tools;
namespace BurnOutSharp.PackerType
{
// Created by IndigoRose (creators of Setup Factory), primarily to be used to create autorun menus for various media.
// Official website: https://www.autoplay.org/
public class AutoPlayMediaStudio : IPEContentCheck, IScannable
{
/// <inheritdoc/>
public bool ShouldScan(byte[] magic) => true;
/// <inheritdoc/>
public string CheckPEContents(string file, PortableExecutable pex, bool includeDebug)
{
// Get the sections from the executable, if possible
var sections = pex?.SectionTable;
if (sections == null)
return null;
// Known to detect versions 5.0.0.3 - 8.1.0.0
string name = pex.ProductName;
if (!string.IsNullOrWhiteSpace(name) && name.StartsWith("AutoPlay Media Studio", StringComparison.OrdinalIgnoreCase))
return $"AutoPlay Media Studio {GetVersion(pex)}";
// Currently too vague, may be re-enabled in the future
/*
name = Utilities.GetLegalCopyright(pex);
if (!string.IsNullOrWhiteSpace(name) && name.StartsWith("Runtime Engine", StringComparison.OrdinalIgnoreCase))
return $"AutoPlay Media Studio {GetVersion(pex)}";
*/
return null;
}
/// <inheritdoc/>
public ConcurrentDictionary<string, ConcurrentQueue<string>> Scan(Scanner scanner, string file)
{
if (!File.Exists(file))
return null;
using (var fs = File.OpenRead(file))
{
return Scan(scanner, fs, file);
}
}
/// <inheritdoc/>
public ConcurrentDictionary<string, ConcurrentQueue<string>> Scan(Scanner scanner, Stream stream, string file)
{
return null;
}
private string GetVersion(PortableExecutable pex)
{
// Check the product version explicitly
string version = pex.ProductVersion;
if (!string.IsNullOrEmpty(version))
return version;
// Check the internal versions
version = Utilities.GetInternalVersion(pex);
if (!string.IsNullOrEmpty(version))
return version;
return "(Unknown Version)";
}
}
}

View File

@@ -19,11 +19,11 @@ namespace BurnOutSharp.PackerType
if (sections == null)
return null;
string name = Utilities.GetFileDescription(pex);
string name = pex.FileDescription;
if (!string.IsNullOrWhiteSpace(name) && name.StartsWith("InstallAnywhere Self Extractor", StringComparison.OrdinalIgnoreCase))
return $"InstallAnywhere {GetVersion(pex)}";
name = Utilities.GetProductName(pex);
name = pex.ProductName;
if (!string.IsNullOrWhiteSpace(name) && name.StartsWith("InstallAnywhere", StringComparison.OrdinalIgnoreCase))
return $"InstallAnywhere {GetVersion(pex)}";
@@ -51,13 +51,8 @@ namespace BurnOutSharp.PackerType
private string GetVersion(PortableExecutable pex)
{
// Check the file version first
string version = Utilities.GetFileVersion(pex);
if (!string.IsNullOrEmpty(version))
return version;
// Then check the manifest version
version = Utilities.GetManifestVersion(pex);
// Check the internal versions
string version = Utilities.GetInternalVersion(pex);
if (!string.IsNullOrEmpty(version))
return version;

View File

@@ -15,20 +15,20 @@ namespace BurnOutSharp.PackerType
if (sections == null)
return null;
string name = Utilities.GetFileDescription(pex);
string name = pex.FileDescription;
if (!string.IsNullOrWhiteSpace(name)
&& (name.Equals("Intel(R) Installation Framework", StringComparison.OrdinalIgnoreCase)
|| name.Equals("Intel Installation Framework", StringComparison.OrdinalIgnoreCase)))
{
return $"Intel Installation Framework {Utilities.GetFileVersion(pex)}";
return $"Intel Installation Framework {Utilities.GetInternalVersion(pex)}";
}
name = Utilities.GetProductName(pex);
name = pex.ProductName;
if (!string.IsNullOrWhiteSpace(name)
&& (name.Equals("Intel(R) Installation Framework", StringComparison.OrdinalIgnoreCase)
|| name.Equals("Intel Installation Framework", StringComparison.OrdinalIgnoreCase)))
{
return $"Intel Installation Framework {Utilities.GetFileVersion(pex)}";
return $"Intel Installation Framework {Utilities.GetInternalVersion(pex)}";
}
return null;

View File

@@ -22,11 +22,11 @@ namespace BurnOutSharp.PackerType
if (sections == null)
return null;
string name = Utilities.GetInternalName(pex);
string name = pex.InternalName;
if (!string.IsNullOrWhiteSpace(name) && name.Equals("Wextract", StringComparison.OrdinalIgnoreCase))
return $"Microsoft CAB SFX {GetVersion(pex)}";
name = Utilities.GetOriginalFileName(pex);
name = pex.OriginalFileName;
if (!string.IsNullOrWhiteSpace(name) && name.Equals("WEXTRACT.EXE", StringComparison.OrdinalIgnoreCase))
return $"Microsoft CAB SFX {GetVersion(pex)}";
@@ -87,11 +87,8 @@ namespace BurnOutSharp.PackerType
private string GetVersion(PortableExecutable pex)
{
string version = Utilities.GetFileVersion(pex);
if (!string.IsNullOrWhiteSpace(version))
return $"v{version}";
version = Utilities.GetManifestVersion(pex);
// Check the internal versions
string version = Utilities.GetInternalVersion(pex);
if (!string.IsNullOrWhiteSpace(version))
return $"v{version}";

View File

@@ -1,7 +1,6 @@
using System.Collections.Generic;
using BurnOutSharp.ExecutableType.Microsoft.PE;
using BurnOutSharp.Matching;
using BurnOutSharp.Tools;
namespace BurnOutSharp.PackerType
{
@@ -15,7 +14,7 @@ namespace BurnOutSharp.PackerType
if (sections == null)
return null;
string description = Utilities.GetManifestDescription(pex);
string description = pex.ManifestDescription;
if (!string.IsNullOrWhiteSpace(description) && description.StartsWith("Nullsoft Install System"))
return $"NSIS {description.Substring("Nullsoft Install System".Length).Trim()}";

View File

@@ -19,11 +19,17 @@ namespace BurnOutSharp.PackerType
if (sections == null)
return null;
string name = Utilities.GetLegalCopyright(pex);
// Known to detect versions 7.0.5.1 - 9.1.0.0
string name = pex.LegalCopyright;
if (!string.IsNullOrWhiteSpace(name) && name.StartsWith("Setup Engine", StringComparison.OrdinalIgnoreCase))
return $"Setup Factory {GetVersion(pex)}";
name = pex.ProductName;
if (!string.IsNullOrWhiteSpace(name) && name.StartsWith("Setup Factory", StringComparison.OrdinalIgnoreCase))
return $"Setup Factory {GetVersion(pex)}";
name = Utilities.GetProductName(pex);
// Known to detect version 5.0.1 - 6.0.1.3
name = pex.FileDescription;
if (!string.IsNullOrWhiteSpace(name) && name.StartsWith("Setup Factory", StringComparison.OrdinalIgnoreCase))
return $"Setup Factory {GetVersion(pex)}";
@@ -55,13 +61,13 @@ namespace BurnOutSharp.PackerType
private string GetVersion(PortableExecutable pex)
{
// Check the manifest version first
string version = Utilities.GetManifestVersion(pex);
// Check the product version explicitly
string version = pex.ProductVersion;
if (!string.IsNullOrEmpty(version))
return version;
// Then check the file version
version = Utilities.GetFileVersion(pex);
// Check the internal versions
version = Utilities.GetInternalVersion(pex);
if (!string.IsNullOrEmpty(version))
return version;

View File

@@ -187,8 +187,8 @@ namespace BurnOutSharp.PackerType
private static string GetAdjustedManifestVersion(PortableExecutable pex)
{
// Get the manifest information, if possible
string description = Utilities.GetManifestDescription(pex);
string version = Utilities.GetManifestVersion(pex);
string description = pex.ManifestDescription;
string version = pex.ManifestVersion;
// Either an incorrect description or empty version mean we can't match
if (description != "WinZip Self-Extractor")

View File

@@ -1,6 +1,5 @@
using System;
using BurnOutSharp.ExecutableType.Microsoft.PE;
using BurnOutSharp.Tools;
namespace BurnOutSharp.ProtectionType
{
@@ -14,7 +13,7 @@ namespace BurnOutSharp.ProtectionType
if (sections == null)
return null;
string name = Utilities.GetInternalName(pex);
string name = pex.InternalName;
if (!string.IsNullOrWhiteSpace(name) && name.Equals("CDKey", StringComparison.OrdinalIgnoreCase))
return "CD-Key / Serial";

View File

@@ -22,21 +22,21 @@ namespace BurnOutSharp.ProtectionType
if (sections == null)
return null;
string name = Utilities.GetFileDescription(pex);
string name = pex.FileDescription;
if (!string.IsNullOrWhiteSpace(name) && name.Contains("EReg MFC Application"))
return $"EA CdKey Registration Module {Utilities.GetFileVersion(pex)}";
return $"EA CdKey Registration Module {Utilities.GetInternalVersion(pex)}";
else if (!string.IsNullOrWhiteSpace(name) && name.Contains("Registration code installer program"))
return $"EA CdKey Registration Module {Utilities.GetFileVersion(pex)}";
return $"EA CdKey Registration Module {Utilities.GetInternalVersion(pex)}";
else if (!string.IsNullOrWhiteSpace(name) && name.Equals("EA DRM Helper", StringComparison.OrdinalIgnoreCase))
return $"EA DRM Protection {Utilities.GetFileVersion(pex)}";
return $"EA DRM Protection {Utilities.GetInternalVersion(pex)}";
name = Utilities.GetInternalName(pex);
name = pex.InternalName;
if (!string.IsNullOrWhiteSpace(name) && name.Equals("CDCode", StringComparison.Ordinal))
return $"EA CdKey Registration Module {Utilities.GetFileVersion(pex)}";
return $"EA CdKey Registration Module {Utilities.GetInternalVersion(pex)}";
var resource = Utilities.FindResourceInSection(pex.ResourceSection, dataContains: "A\0b\0o\0u\0t\0 \0C\0D\0K\0e\0y");
var resource = pex.FindResource(dataContains: "A\0b\0o\0u\0t\0 \0C\0D\0K\0e\0y");
if (resource != null)
return $"EA CdKey Registration Module {Utilities.GetFileVersion(pex)}";
return $"EA CdKey Registration Module {Utilities.GetInternalVersion(pex)}";
// Get the .data section, if it exists
if (pex.DataSectionRaw != null)
@@ -48,7 +48,7 @@ namespace BurnOutSharp.ProtectionType
{
0x45, 0x52, 0x65, 0x67, 0x20, 0x43, 0x6F, 0x6E,
0x66, 0x69, 0x67, 0x20, 0x46, 0x6F, 0x72, 0x6D
}, Utilities.GetFileVersion, "EA CdKey Registration Module"),
}, Utilities.GetInternalVersion, "EA CdKey Registration Module"),
};
string match = MatchUtil.GetFirstMatch(file, pex.DataSectionRaw, matchers, includeDebug);

View File

@@ -17,11 +17,11 @@ namespace BurnOutSharp.ProtectionType
if (sections == null)
return null;
string name = Utilities.GetFileDescription(pex);
string name = pex.FileDescription;
if (!string.IsNullOrWhiteSpace(name) && name.StartsWith("Games for Windows - LIVE Zero Day Piracy Protection", StringComparison.OrdinalIgnoreCase))
return $"Games for Windows LIVE - Zero Day Piracy Protection Module {Utilities.GetFileVersion(pex)}";
return $"Games for Windows LIVE - Zero Day Piracy Protection Module {Utilities.GetInternalVersion(pex)}";
else if (!string.IsNullOrWhiteSpace(name) && name.StartsWith("Games for Windows", StringComparison.OrdinalIgnoreCase))
return $"Games for Windows LIVE {Utilities.GetFileVersion(pex)}";
return $"Games for Windows LIVE {Utilities.GetInternalVersion(pex)}";
// Get the .rdata section, if it exists
if (pex.ResourceDataSectionRaw != null)

View File

@@ -18,17 +18,17 @@ namespace BurnOutSharp.ProtectionType
if (sections == null)
return null;
string name = Utilities.GetFileDescription(pex);
string name = pex.FileDescription;
if (!string.IsNullOrWhiteSpace(name) && name.Contains("ImpulseReactor Dynamic Link Library"))
return $"Impulse Reactor Core Module {Utilities.GetFileVersion(pex)}";
return $"Impulse Reactor Core Module {Utilities.GetInternalVersion(pex)}";
name = Utilities.GetProductName(pex);
name = pex.ProductName;
if (!string.IsNullOrWhiteSpace(name) && name.Contains("ImpulseReactor Dynamic Link Library"))
return $"Impulse Reactor Core Module {Utilities.GetFileVersion(pex)}";
return $"Impulse Reactor Core Module {Utilities.GetInternalVersion(pex)}";
name = Utilities.GetOriginalFileName(pex);
name = pex.OriginalFileName;
if (!string.IsNullOrWhiteSpace(name) && name.Contains("ReactorActivate.exe"))
return $"Stardock Product Activation {Utilities.GetFileVersion(pex)}";
return $"Stardock Product Activation {Utilities.GetInternalVersion(pex)}";
// Get the .rdata section, if it exists
if (pex.ResourceDataSectionRaw != null)
@@ -56,7 +56,7 @@ namespace BurnOutSharp.ProtectionType
bool containsCheck2 = pex.ResourceDataSectionRaw.FirstPosition(check2, out int position2);
if (containsCheck && containsCheck2)
return $"Impulse Reactor Core Module {Utilities.GetFileVersion(pex)}" + (includeDebug ? $" (Index {position}, {position2})" : string.Empty);
return $"Impulse Reactor Core Module {Utilities.GetInternalVersion(pex)}" + (includeDebug ? $" (Index {position}, {position2})" : string.Empty);
else if (containsCheck && !containsCheck2)
return $"Impulse Reactor" + (includeDebug ? $" (Index {position})" : string.Empty);
}
@@ -69,8 +69,8 @@ namespace BurnOutSharp.ProtectionType
{
var matchers = new List<PathMatchSet>
{
new PathMatchSet(new PathMatch("ImpulseReactor.dll", useEndsWith: true), Utilities.GetFileVersion, "Impulse Reactor Core Module"),
new PathMatchSet(new PathMatch("ReactorActivate.exe", useEndsWith: true), Utilities.GetFileVersion, "Stardock Product Activation"),
new PathMatchSet(new PathMatch("ImpulseReactor.dll", useEndsWith: true), Utilities.GetInternalVersion, "Impulse Reactor Core Module"),
new PathMatchSet(new PathMatch("ReactorActivate.exe", useEndsWith: true), Utilities.GetInternalVersion, "Stardock Product Activation"),
};
return MatchUtil.GetAllMatches(files, matchers, any: true);
@@ -81,8 +81,8 @@ namespace BurnOutSharp.ProtectionType
{
var matchers = new List<PathMatchSet>
{
new PathMatchSet(new PathMatch("ImpulseReactor.dll", useEndsWith: true), Utilities.GetFileVersion, "Impulse Reactor Core Module"),
new PathMatchSet(new PathMatch("ReactorActivate.exe", useEndsWith: true), Utilities.GetFileVersion, "Stardock Product Activation"),
new PathMatchSet(new PathMatch("ImpulseReactor.dll", useEndsWith: true), Utilities.GetInternalVersion, "Impulse Reactor Core Module"),
new PathMatchSet(new PathMatch("ReactorActivate.exe", useEndsWith: true), Utilities.GetInternalVersion, "Stardock Product Activation"),
};
return MatchUtil.GetFirstMatch(path, matchers, any: true);

View File

@@ -1,5 +1,4 @@
using BurnOutSharp.ExecutableType.Microsoft.PE;
using BurnOutSharp.Tools;
namespace BurnOutSharp.ProtectionType
{
@@ -29,7 +28,7 @@ namespace BurnOutSharp.ProtectionType
if (sections == null)
return null;
var fileNameResource = Utilities.FindResourceInSection(pex.ResourceSection, dataContains: $"NO NESTED PRMS SUPPORTED");
var fileNameResource = pex.FindResource(dataContains: $"NO NESTED PRMS SUPPORTED");
if (fileNameResource != null)
return "ITENIUM Trial & Buy Protection";

View File

@@ -2,7 +2,6 @@
using System.Collections.Generic;
using BurnOutSharp.ExecutableType.Microsoft.PE;
using BurnOutSharp.Matching;
using BurnOutSharp.Tools;
namespace BurnOutSharp.ProtectionType
{
@@ -16,7 +15,7 @@ namespace BurnOutSharp.ProtectionType
if (sections == null)
return null;
string name = Utilities.GetFileDescription(pex);
string name = pex.FileDescription;
if (!string.IsNullOrWhiteSpace(name) && name.Contains("SDKHM (KEEP)"))
return "key2AudioXS";
else if (!string.IsNullOrWhiteSpace(name) && name.Contains("SDKHM (KEPT)"))

View File

@@ -2,7 +2,6 @@
using System.Collections.Generic;
using BurnOutSharp.ExecutableType.Microsoft.PE;
using BurnOutSharp.Matching;
using BurnOutSharp.Tools;
namespace BurnOutSharp.ProtectionType
{
@@ -16,7 +15,7 @@ namespace BurnOutSharp.ProtectionType
if (sections == null)
return null;
var resource = Utilities.FindResourceInSection(pex.ResourceSection, dataContains: "Cd3Ctl");
var resource = pex.FindResource(dataContains: "Cd3Ctl");
if (resource != null)
return $"MediaMax CD-3";

View File

@@ -15,9 +15,9 @@ namespace BurnOutSharp.ProtectionType
return null;
// TODO: Is this too broad in general?
string name = Utilities.GetInternalName(pex);
string name = pex.InternalName;
if (!string.IsNullOrWhiteSpace(name) && name.StartsWith("EReg", StringComparison.OrdinalIgnoreCase))
return $"Executable-Based Online Registration {Utilities.GetFileVersion(pex)}";
return $"Executable-Based Online Registration {Utilities.GetInternalVersion(pex)}";
return null;
}

View File

@@ -3,7 +3,6 @@ using System.Collections.Concurrent;
using System.Collections.Generic;
using BurnOutSharp.ExecutableType.Microsoft.PE;
using BurnOutSharp.Matching;
using BurnOutSharp.Tools;
namespace BurnOutSharp.ProtectionType
{
@@ -17,11 +16,11 @@ namespace BurnOutSharp.ProtectionType
if (sections == null)
return null;
string name = Utilities.GetFileDescription(pex);
string name = pex.FileDescription;
if (!string.IsNullOrWhiteSpace(name) && name.Equals("Origin", StringComparison.OrdinalIgnoreCase))
return "Origin";
name = Utilities.GetProductName(pex);
name = pex.ProductName;
if (!string.IsNullOrWhiteSpace(name) && name.Equals("Origin", StringComparison.OrdinalIgnoreCase))
return "Origin";

View File

@@ -54,7 +54,7 @@ namespace BurnOutSharp.ProtectionType
if (sections == null)
return null;
string name = Utilities.GetFileDescription(pex);
string name = pex.FileDescription;
if (!string.IsNullOrWhiteSpace(name) && name.Equals("SafeCast2", StringComparison.OrdinalIgnoreCase))
return $"SafeCast";

View File

@@ -1,4 +1,5 @@
using System.Collections.Concurrent;
using System.IO;
using System.Collections.Concurrent;
using System.Collections.Generic;
using BurnOutSharp.Matching;
@@ -24,7 +25,7 @@ namespace BurnOutSharp.ProtectionType
// Technically all need to exist but some might be renamed
var matchers = new List<PathMatchSet>
{
new PathMatchSet(new PathMatch("SafeLock.DAT", useEndsWith: true), "SafeLock"),
new PathMatchSet(new PathMatch($"{Path.DirectorySeparatorChar}SafeLock.DAT", useEndsWith: true), "SafeLock"),
new PathMatchSet(new PathMatch("SafeLock.001", useEndsWith: true), "SafeLock"),
new PathMatchSet(new PathMatch("SafeLock.002", useEndsWith: true), "SafeLock"),
new PathMatchSet(new PathMatch("SafeLock.128", useEndsWith: true), "SafeLock"),
@@ -39,7 +40,7 @@ namespace BurnOutSharp.ProtectionType
{
var matchers = new List<PathMatchSet>
{
new PathMatchSet(new PathMatch("SafeLock.DAT", useEndsWith: true), "SafeLock"),
new PathMatchSet(new PathMatch($"{Path.DirectorySeparatorChar}SafeLock.DAT", useEndsWith: true), "SafeLock"),
new PathMatchSet(new PathMatch("SafeLock.001", useEndsWith: true), "SafeLock"),
new PathMatchSet(new PathMatch("SafeLock.002", useEndsWith: true), "SafeLock"),
new PathMatchSet(new PathMatch("SafeLock.128", useEndsWith: true), "SafeLock"),

View File

@@ -20,9 +20,9 @@ namespace BurnOutSharp.ProtectionType
if (sections == null)
return null;
string name = Utilities.GetFileDescription(pex);
string name = pex.FileDescription;
if (!string.IsNullOrWhiteSpace(name) && name.Contains("SecuROM PA"))
return $"SecuROM PA v{Utilities.GetFileVersion(pex)}";
return $"SecuROM PA v{Utilities.GetInternalVersion(pex)}";
// Get the matrosch section, if it exists
bool matroschSection = pex.ContainsSection("matrosch", exact: true);
@@ -101,7 +101,7 @@ namespace BurnOutSharp.ProtectionType
{
0x64, 0x72, 0x6D, 0x5F, 0x70, 0x61, 0x67, 0x75,
0x69, 0x5F, 0x64, 0x6F, 0x69, 0x74
}, Utilities.GetFileVersion, "SecuROM Product Activation"),
}, Utilities.GetInternalVersion, "SecuROM Product Activation"),
// TODO: Re-enable this one if the above undermatches somehow
// // S + (char)0x00 + e + (char)0x00 + c + (char)0x00 + u + (char)0x00 + R + (char)0x00 + O + (char)0x00 + M + (char)0x00 + + (char)0x00 + P + (char)0x00 + A + (char)0x00
@@ -110,7 +110,7 @@ namespace BurnOutSharp.ProtectionType
// 0x53, 0x00, 0x65, 0x00, 0x63, 0x00, 0x75, 0x00,
// 0x52, 0x00, 0x4F, 0x00, 0x4D, 0x00, 0x20, 0x00,
// 0x50, 0x00, 0x41, 0x00
// }, Utilities.GetFileVersion, "SecuROM Product Activation"),
// }, Utilities.GetInternalVersion, "SecuROM Product Activation"),
};
string match = MatchUtil.GetFirstMatch(file, pex.ResourceDataSectionRaw, matchers, includeDebug);

View File

@@ -20,21 +20,21 @@ namespace BurnOutSharp.ProtectionType
if (sections == null)
return null;
string name = Utilities.GetFileDescription(pex);
string name = pex.FileDescription;
if (!string.IsNullOrWhiteSpace(name) && name.StartsWith("DVM Library", StringComparison.OrdinalIgnoreCase))
return $"SolidShield {Utilities.GetFileVersion(pex)}";
return $"SolidShield {Utilities.GetInternalVersion(pex)}";
else if (!string.IsNullOrWhiteSpace(name) && name.StartsWith("Solidshield Activation Library", StringComparison.OrdinalIgnoreCase))
return $"SolidShield Core.dll {Utilities.GetFileVersion(pex)}";
return $"SolidShield Core.dll {Utilities.GetInternalVersion(pex)}";
else if (!string.IsNullOrWhiteSpace(name) && name.StartsWith("Activation Manager", StringComparison.OrdinalIgnoreCase))
return $"SolidShield Activation Manager Module {GetFileVersion(pex)}";
return $"SolidShield Activation Manager Module {GetInternalVersion(pex)}";
name = Utilities.GetProductName(pex);
name = pex.ProductName;
if (!string.IsNullOrWhiteSpace(name) && name.StartsWith("Solidshield Activation Library", StringComparison.OrdinalIgnoreCase))
return $"SolidShield Core.dll {Utilities.GetFileVersion(pex)}";
return $"SolidShield Core.dll {Utilities.GetInternalVersion(pex)}";
else if (!string.IsNullOrWhiteSpace(name) && name.StartsWith("Solidshield Library", StringComparison.OrdinalIgnoreCase))
return $"SolidShield Core.dll {Utilities.GetFileVersion(pex)}";
return $"SolidShield Core.dll {Utilities.GetInternalVersion(pex)}";
else if (!string.IsNullOrWhiteSpace(name) && name.StartsWith("Activation Manager", StringComparison.OrdinalIgnoreCase))
return $"SolidShield Activation Manager Module {GetFileVersion(pex)}";
return $"SolidShield Activation Manager Module {GetInternalVersion(pex)}";
// Get the .init section, if it exists
var initSectionRaw = pex.ReadRawSection(".init", first: true);
@@ -58,7 +58,7 @@ namespace BurnOutSharp.ProtectionType
}
// Get the wrapper resource, if it exists
var resource = Utilities.FindResourceInSection(pex.ResourceSection, dataContains: "B\0I\0N\0" + (char)0x07 + "\0I\0D\0R\0_\0S\0G\0T\0");
var resource = pex.FindResource(dataContains: "B\0I\0N\0" + (char)0x07 + "\0I\0D\0R\0_\0S\0G\0T\0");
if (resource != null)
return "SolidShield EXE Wrapper v1";
@@ -188,11 +188,11 @@ namespace BurnOutSharp.ProtectionType
return null;
}
private static string GetFileVersion(PortableExecutable pex)
private static string GetInternalVersion(PortableExecutable pex)
{
string companyName = Utilities.GetCompanyName(pex)?.ToLowerInvariant();
string companyName = pex.CompanyName?.ToLowerInvariant();
if (!string.IsNullOrWhiteSpace(companyName) && (companyName.Contains("solidshield") || companyName.Contains("tages")))
return Utilities.GetFileVersion(pex);
return Utilities.GetInternalVersion(pex);
return null;
}

View File

@@ -1,7 +1,6 @@
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Text;
using BurnOutSharp.ExecutableType.Microsoft.PE;
using BurnOutSharp.Matching;
using BurnOutSharp.Tools;
@@ -18,18 +17,18 @@ namespace BurnOutSharp.ProtectionType
if (sections == null)
return null;
string name = Utilities.GetLegalCopyright(pex);
string name = pex.LegalCopyright;
if (!string.IsNullOrWhiteSpace(name) && name.Contains("Protection Technology")) // Protection Technology (StarForce)?
return $"StarForce {Utilities.GetFileVersion(pex)}";
return $"StarForce {Utilities.GetInternalVersion(pex)}";
name = Utilities.GetInternalName(pex);
name = pex.InternalName;
if (!string.IsNullOrWhiteSpace(name) && name.Equals("CORE.EXE", StringComparison.Ordinal))
return $"StarForce {Utilities.GetFileVersion(pex)}";
return $"StarForce {Utilities.GetInternalVersion(pex)}";
else if (!string.IsNullOrWhiteSpace(name) && name.Equals("protect.exe", StringComparison.Ordinal))
return $"StarForce {Utilities.GetFileVersion(pex)}";
return $"StarForce {Utilities.GetInternalVersion(pex)}";
// TODO: Find what fvinfo field actually maps to this
name = Utilities.GetFileDescription(pex);
name = pex.FileDescription;
if (!string.IsNullOrWhiteSpace(name) && name.Contains("Protected Module"))
return $"StarForce 5";
@@ -139,7 +138,7 @@ namespace BurnOutSharp.ProtectionType
// }, GetVersion, "StarForce"),
// public static string GetVersion(string file, byte[] fileContent, List<int> positions)
// {
// return $"{Utilities.GetFileVersion(fileContent)} ({fileContent.Skip(positions[1] + 22).TakeWhile(c => c != 0x00)})";
// return $"{Utilities.GetInternalVersion(fileContent)} ({fileContent.Skip(positions[1] + 22).TakeWhile(c => c != 0x00)})";
// }
}
}

View File

@@ -16,17 +16,17 @@ namespace BurnOutSharp.ProtectionType
if (sections == null)
return null;
string name = Utilities.GetFileDescription(pex);
string name = pex.FileDescription;
if (!string.IsNullOrEmpty(name) && name.Contains("Steam Autorun Setup"))
return "Steam";
else if (!string.IsNullOrEmpty(name) && name.Contains("Steam Client API"))
return "Steam";
else if (!string.IsNullOrEmpty(name) && name.Contains("Steam Client Engine"))
return $"Steam Client Engine {Utilities.GetFileVersion(pex)}";
return $"Steam Client Engine {Utilities.GetInternalVersion(pex)}";
else if (!string.IsNullOrEmpty(name) && name.Contains("Steam Client Service"))
return "Steam";
name = Utilities.GetProductName(pex);
name = pex.ProductName;
if (!string.IsNullOrEmpty(name) && name.Contains("Steam Autorun Setup"))
return "Steam";
else if (!string.IsNullOrEmpty(name) && name.Contains("Steam Client API"))

View File

@@ -28,13 +28,13 @@ namespace BurnOutSharp.ProtectionType
// - TagesClient.exe
// - TagesClient.dat (Does not always exist)
string name = Utilities.GetFileDescription(pex);
string name = pex.FileDescription;
if (!string.IsNullOrWhiteSpace(name) && name.StartsWith("TagesSetup", StringComparison.OrdinalIgnoreCase))
return $"TAGES Driver Setup {GetVersion(pex)}";
else if (!string.IsNullOrWhiteSpace(name) && name.StartsWith("Tagès activation client", StringComparison.OrdinalIgnoreCase))
return $"TAGES Activation Client {GetVersion(pex)}";
name = Utilities.GetProductName(pex);
name = pex.ProductName;
if (!string.IsNullOrWhiteSpace(name) && name.StartsWith("Application TagesSetup", StringComparison.OrdinalIgnoreCase))
return $"TAGES Driver Setup {GetVersion(pex)}";
else if (!string.IsNullOrWhiteSpace(name) && name.StartsWith("T@GES", StringComparison.OrdinalIgnoreCase))
@@ -180,13 +180,8 @@ namespace BurnOutSharp.ProtectionType
private string GetVersion(PortableExecutable pex)
{
// Check the file version first
string version = Utilities.GetFileVersion(pex);
if (!string.IsNullOrEmpty(version))
return version;
// Then check the manifest version
version = Utilities.GetManifestVersion(pex);
// Check the internal versions
string version = Utilities.GetInternalVersion(pex);
if (!string.IsNullOrEmpty(version))
return version;

View File

@@ -1,5 +1,4 @@
using BurnOutSharp.ExecutableType.Microsoft.PE;
using BurnOutSharp.Tools;
namespace BurnOutSharp.ProtectionType
{
@@ -13,7 +12,7 @@ namespace BurnOutSharp.ProtectionType
if (sections == null)
return null;
var resource = Utilities.FindResourceInSection(pex.ResourceSection, dataContains: "3\02\01\0S\0t\0u\0d\0i\0o\0s\0 \0A\0c\0t\0i\0v\0a\0t\0i\0o\0n\0");
var resource = pex.FindResource(dataContains: "3\02\01\0S\0t\0u\0d\0i\0o\0s\0 \0A\0c\0t\0i\0v\0a\0t\0i\0o\0n\0");
if (resource != null)
return $"321Studios Online Activation";

View File

@@ -2,7 +2,6 @@
using System.Collections.Generic;
using BurnOutSharp.ExecutableType.Microsoft.PE;
using BurnOutSharp.Matching;
using BurnOutSharp.Tools;
namespace BurnOutSharp.ProtectionType
{
@@ -17,7 +16,7 @@ namespace BurnOutSharp.ProtectionType
if (sections == null)
return null;
string name = Utilities.GetFileDescription(pex);
string name = pex.FileDescription;
if (!string.IsNullOrEmpty(name) && name.Contains("Ubisoft Connect Installer"))
return "Uplay / Ubisoft Connect";
else if (!string.IsNullOrEmpty(name) && name.Contains("Ubisoft Connect Service"))
@@ -34,7 +33,7 @@ namespace BurnOutSharp.ProtectionType
return "Uplay / Ubisoft Connect";
// There's also a variant that looks like "Uplay <version> installer"
name = Utilities.GetProductName(pex);
name = pex.ProductName;
if (!string.IsNullOrEmpty(name) && name.Contains("Ubisoft Connect"))
return "Uplay / Ubisoft Connect";
else if (!string.IsNullOrEmpty(name) && name.Contains("Uplay"))

View File

@@ -2,7 +2,6 @@
using System.Collections.Generic;
using BurnOutSharp.ExecutableType.Microsoft.PE;
using BurnOutSharp.Matching;
using BurnOutSharp.Tools;
namespace BurnOutSharp.ProtectionType
{
@@ -16,11 +15,11 @@ namespace BurnOutSharp.ProtectionType
if (sections == null)
return null;
string name = Utilities.GetFileDescription(pex);
string name = pex.FileDescription;
if (!string.IsNullOrEmpty(name) && name.Contains("Copy Protection Viewer"))
return "WTM Protection Viewer";
name = Utilities.GetProductName(pex);
name = pex.ProductName;
if (!string.IsNullOrEmpty(name) && name.Contains("WTM Copy Protection Viewer"))
return "WTM Protection Viewer";

View File

@@ -4,12 +4,7 @@ using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Xml;
using BurnOutSharp.ExecutableType.Microsoft.PE;
using BurnOutSharp.ExecutableType.Microsoft.PE.Entries;
using BurnOutSharp.ExecutableType.Microsoft.PE.Sections;
using BurnOutSharp.ExecutableType.Microsoft.PE.Tables;
using BurnOutSharp.ExecutableType.Microsoft.Resources;
namespace BurnOutSharp.Tools
{
@@ -181,41 +176,49 @@ namespace BurnOutSharp.Tools
#endregion
#region Executable Information
#region Processed Executable Information
/// <summary>
/// Get the company name as reported by the filesystem
/// </summary>
/// <param name="pex">PortableExecutable representing the file contents</param>
/// <returns>Company name string, null on error</returns>
public static string GetCompanyName(PortableExecutable pex) => GetResourceString(pex, "CompanyName");
/// <summary>
/// Get the file description as reported by the filesystem
/// </summary>
/// <param name="pex">PortableExecutable representing the file contents</param>
/// <returns>Description string, null on error</returns>
public static string GetFileDescription(PortableExecutable pex) => GetResourceString(pex, "FileDescription");
/// <summary>
/// Get the file version as reported by the filesystem
/// Get the internal version as reported by the resources
/// </summary>
/// <param name="fileContent">Byte array representing the file contents</param>
/// <returns>Version string, null on error</returns>
public static string GetFileVersion(byte[] fileContent)
public static string GetInternalVersion(byte[] fileContent)
{
if (fileContent == null || !fileContent.Any())
return null;
return GetFileVersion(new PortableExecutable(fileContent, 0));
return GetInternalVersion(new PortableExecutable(fileContent, 0));
}
/// <summary>
/// Get the file version as reported by the filesystem
/// Get the internal version as reported by the resources
/// </summary>
/// <param name="pex">PortableExecutable representing the file contents</param>
/// <returns>Version string, null on error</returns>
public static string GetInternalVersion(PortableExecutable pex)
{
string version = pex.FileVersion;
if (!string.IsNullOrWhiteSpace(version))
return version;
version = pex.ProductVersion;
if (!string.IsNullOrWhiteSpace(version))
return version;
version = pex.ManifestVersion;
if (!string.IsNullOrWhiteSpace(version))
return version;
return null;
}
/// <summary>
/// Get the internal version as reported by the filesystem
/// </summary>
/// <param name="file">File to check for version</param>
/// <returns>Version string, null on error</returns>
public static string GetFileVersion(string file)
public static string GetInternalVersion(string file)
{
var fvinfo = GetFileVersionInfo(file);
if (fvinfo?.FileVersion == null)
@@ -225,257 +228,10 @@ namespace BurnOutSharp.Tools
else
return fvinfo.ProductVersion.Replace(", ", ".");
}
/// <summary>
/// Get the file version as reported by the filesystem
/// </summary>
/// <param name="pex">PortableExecutable representing the file contents</param>
/// <returns>Version string, null on error</returns>
public static string GetFileVersion(PortableExecutable pex)
{
string version = GetResourceString(pex, "FileVersion");
if (!string.IsNullOrWhiteSpace(version))
return version.Replace(", ", ".");
version = GetResourceString(pex, "ProductVersion");
if (!string.IsNullOrWhiteSpace(version))
return version.Replace(", ", ".");
#endregion
return null;
}
/// <summary>
/// Wrapper for GetFileVersion for use in content matching
/// </summary>
/// <param name="file">File to check for version</param>
/// <param name="fileContent">Byte array representing the file contents</param>
/// <param name="positions">Last matched positions in the contents</param>
/// <returns>Version string, null on error</returns>
public static string GetFileVersion(string file, byte[] fileContent, List<int> positions) => GetFileVersion(fileContent);
/// <summary>
/// Wrapper for GetFileVersion for use in path matching
/// </summary>
/// <param name="firstMatchedString">File to check for version</param>
/// <param name="files">Full list of input paths</param>
/// <returns>Version string, null on error</returns>
public static string GetFileVersion(string firstMatchedString, IEnumerable<string> files) => GetFileVersion(firstMatchedString);
/// <summary>
/// Get the internal name as reported by the filesystem
/// </summary>
/// <param name="pex">PortableExecutable representing the file contents</param>
/// <returns>Internal name string, null on error</returns>
public static string GetInternalName(PortableExecutable pex) => GetResourceString(pex, "InternalName");
/// <summary>
/// Get the legal copyright as reported by the filesystem
/// </summary>
/// <param name="pex">PortableExecutable representing the file contents</param>
/// <returns>Legal copyright string, null on error</returns>
public static string GetLegalCopyright(PortableExecutable pex) => GetResourceString(pex, "LegalCopyright");
/// <summary>
/// Get the assembly version as determined by an embedded assembly manifest
/// </summary>
/// <param name="fileContent">Byte array representing the file contents</param>
/// <returns>Version string, null on error</returns>
public static string GetManifestDescription(PortableExecutable pex)
{
// If we don't have a PE executable, just return null
var resourceSection = pex?.ResourceSection;
if (resourceSection == null)
return null;
// Read in the manifest to a string
string manifestString = FindAssemblyManifest(pex.ResourceSection);
if (string.IsNullOrWhiteSpace(manifestString))
return null;
// Try to read the XML in from the string
try
{
// Try to read the assembly
var assemblyNode = GetAssemblyNode(manifestString);
if (assemblyNode == null)
return null;
// Return the content of the description node, if possible
var descriptionNode = assemblyNode["description"];
if (descriptionNode == null)
return null;
return descriptionNode.InnerXml;
}
catch
{
return null;
}
}
/// <summary>
/// Get the assembly version as determined by an embedded assembly manifest
/// </summary>
/// <param name="pex">PortableExecutable representing the file contents</param>
/// <returns>Version string, null on error</returns>
public static string GetManifestVersion(PortableExecutable pex)
{
// If we don't have a PE executable, just return null
var resourceSection = pex?.ResourceSection;
if (resourceSection == null)
return null;
// Read in the manifest to a string
string manifestString = FindAssemblyManifest(pex.ResourceSection);
if (string.IsNullOrWhiteSpace(manifestString))
return null;
// Try to read the XML in from the string
try
{
// Try to read the assembly
var assemblyNode = GetAssemblyNode(manifestString);
if (assemblyNode == null)
return null;
// Try to read the assemblyIdentity
var assemblyIdentityNode = assemblyNode["assemblyIdentity"];
if (assemblyIdentityNode == null)
return null;
// Return the version attribute, if possible
return assemblyIdentityNode.GetAttribute("version");
}
catch
{
return null;
}
}
/// <summary>
/// Get the original filename as reported by the filesystem
/// </summary>
/// <param name="pex">PortableExecutable representing the file contents</param>
/// <returns>Original filename string, null on error</returns>
public static string GetOriginalFileName(PortableExecutable pex) => GetResourceString(pex, "OriginalFileName");
/// <summary>
/// Get the product name as reported by the filesystem
/// </summary>
/// <param name="pex">PortableExecutable representing the file contents</param>
/// <returns>Product name string, null on error</returns>
public static string GetProductName(PortableExecutable pex) => GetResourceString(pex, "ProductName");
/// <summary>
/// Find resource data in a ResourceSection, if possible
/// </summary>
/// <param name="rs">ResourceSection from the executable</param>
/// <param name="dataStart">String to use if checking for data starting with a string</param>
/// <param name="dataContains">String to use if checking for data contains a string</param>
/// <param name="dataEnd">String to use if checking for data ending with a string</param>
/// <returns>Full encoded resource data, null on error</returns>
public static ResourceDataEntry FindResourceInSection(ResourceSection rs, string dataStart = null, string dataContains = null, string dataEnd = null)
{
if (rs == null)
return null;
return FindResourceInTable(rs.ResourceDirectoryTable, dataStart, dataContains, dataEnd);
}
/// <summary>
/// Find resource data in a ResourceDirectoryTable, if possible
/// </summary>
/// <param name="rdt">ResourceDirectoryTable representing a layer</param>
/// <param name="dataStart">String to use if checking for data starting with a string</param>
/// <param name="dataContains">String to use if checking for data contains a string</param>
/// <param name="dataEnd">String to use if checking for data ending with a string</param>
/// <returns>Full encoded resource data, null on error</returns>
private static ResourceDataEntry FindResourceInTable(ResourceDirectoryTable rdt, string dataStart, string dataContains, string dataEnd)
{
if (rdt == null)
return null;
try
{
foreach (var rdte in rdt.NamedEntries)
{
if (rdte.IsResourceDataEntry() && rdte.DataEntry != null)
{
if (dataStart != null && rdte.DataEntry.DataAsUTF8String.StartsWith(dataStart))
return rdte.DataEntry;
else if (dataContains != null && rdte.DataEntry.DataAsUTF8String.Contains(dataContains))
return rdte.DataEntry;
else if (dataEnd != null && rdte.DataEntry.DataAsUTF8String.EndsWith(dataStart))
return rdte.DataEntry;
}
else
{
var manifest = FindResourceInTable(rdte.Subdirectory, dataStart, dataContains, dataEnd);
if (manifest != null)
return manifest;
}
}
foreach (var rdte in rdt.IdEntries)
{
if (rdte.IsResourceDataEntry() && rdte.DataEntry != null)
{
if (dataStart != null && rdte.DataEntry.DataAsUTF8String.StartsWith(dataStart))
return rdte.DataEntry;
else if (dataContains != null && rdte.DataEntry.DataAsUTF8String.Contains(dataContains))
return rdte.DataEntry;
else if (dataEnd != null && rdte.DataEntry.DataAsUTF8String.EndsWith(dataStart))
return rdte.DataEntry;
}
else
{
var manifest = FindResourceInTable(rdte.Subdirectory, dataStart, dataContains, dataEnd);
if (manifest != null)
return manifest;
}
}
}
catch { }
return null;
}
/// <summary>
/// Find the assembly manifest from a resource section, if possible
/// </summary>
/// <param name="rs">ResourceSection from the executable</param>
/// <returns>Full assembly manifest, null on error</returns>
private static string FindAssemblyManifest(ResourceSection rs) => FindResourceInSection(rs, dataContains: "<assembly")?.DataAsUTF8String;
/// <summary>
/// Get the assembly identity node from an embedded manifest
/// </summary>
/// <param name="manifestString">String representing the XML document</param>
/// <returns>Assembly identity node, if possible</returns>
private static XmlElement GetAssemblyNode(string manifestString)
{
// An invalid string means we can't read it
if (string.IsNullOrWhiteSpace(manifestString))
return null;
try
{
// Load the XML string as a document
var manifestDoc = new XmlDocument();
manifestDoc.LoadXml(manifestString);
// If the XML has no children, it's invalid
if (!manifestDoc.HasChildNodes)
return null;
// Try to read the assembly node
return manifestDoc["assembly"];
}
catch (Exception ex)
{
return null;
}
}
#region Executable Information
/// <summary>
/// Get the file version info object related to a path, if possible
@@ -497,52 +253,26 @@ namespace BurnOutSharp.Tools
}
}
/// <summary>
/// Get a resource string from the version info
/// </summary>
/// <param name="pex">PortableExecutable representing the file contents</param>
/// <returns>Original filename string, null on error</returns>
private static string GetResourceString(PortableExecutable pex, string key)
{
var resourceStrings = GetVersionInfo(pex)?.ChildrenStringFileInfo?.Children?.Children;
if (resourceStrings == null)
return null;
var value = resourceStrings.FirstOrDefault(s => s.Key == key);
if (!string.IsNullOrWhiteSpace(value?.Value))
return value.Value.Trim(' ', '\0');
#endregion
return null;
}
#region Wrappers for Matchers
/// <summary>
/// Get the version info object related to file contents, if possible
/// Wrapper for GetInternalVersion for use in content matching
/// </summary>
/// <param name="pex">PortableExecutable representing the file contents</param>
/// <returns>VersionInfo object on success, null on error</returns>
private static VersionInfo GetVersionInfo(PortableExecutable pex)
{
// If we don't have a PE executable, just return null
var resourceSection = pex?.ResourceSection;
if (resourceSection == null)
return null;
/// <param name="file">File to check for version</param>
/// <param name="fileContent">Byte array representing the file contents</param>
/// <param name="positions">Last matched positions in the contents</param>
/// <returns>Version string, null on error</returns>
public static string GetInternalVersion(string file, byte[] fileContent, List<int> positions) => GetInternalVersion(fileContent);
// Try to get the matching resource
var resource = FindResourceInSection(resourceSection, dataContains: "V\0S\0_\0V\0E\0R\0S\0I\0O\0N\0_\0I\0N\0F\0O\0");
if (resource?.Data == null)
return null;
try
{
int index = 0;
return VersionInfo.Deserialize(resource.Data, ref index);
}
catch (Exception ex)
{
// Console.WriteLine(ex);
return null;
}
}
/// <summary>
/// Wrapper for GetInternalVersion for use in path matching
/// </summary>
/// <param name="firstMatchedString">File to check for version</param>
/// <param name="files">Full list of input paths</param>
/// <returns>Version string, null on error</returns>
public static string GetInternalVersion(string firstMatchedString, IEnumerable<string> files) => GetInternalVersion(firstMatchedString);
#endregion
}

View File

@@ -113,6 +113,7 @@ Below is a list of executable packers detected by BurnOutSharp. The three column
| --------------- | ------------- | ---------- | ----------- |
| Advanced Installer / Caphyon Advanced Installer | Yes | No | No |
| Armadillo | Yes | No | No |
| AutoPlay Media Studio | Yes | No | No |
| CExe | Yes | No | No |
| dotFuscator | Yes | No | No |
| EXE Stealth | Yes | No | No |

View File

@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>net48;netcoreapp3.1;net5.0</TargetFrameworks>
<TargetFrameworks>net48;netcoreapp3.1;net5.0;net6.0</TargetFrameworks>
<PlatformTarget>x86</PlatformTarget>
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
<OutputType>Exe</OutputType>

View File

@@ -1,12 +1,12 @@
# version format
version: 1.8.0-{build}
version: 2.1.0-{build}
# pull request template
pull_requests:
do_not_increment_build_number: true
# vm template
image: Visual Studio 2019
image: Visual Studio 2022
# environment variables
environment:
@@ -39,6 +39,7 @@ after_build:
- 7z a BurnOutSharp_net48.zip net48\*
- 7z a BurnOutSharp_netcoreapp3.1.zip netcoreapp3.1\*
- 7z a BurnOutSharp_net5.0.zip net5.0\*
- 7z a BurnOutSharp_net6.0.zip net6.0\*
# success/failure tracking
on_success:
@@ -55,4 +56,6 @@ artifacts:
- path: Test\bin\Debug\BurnOutSharp_netcoreapp3.1.zip
name: BurnOutSharp (.NET Core 3.1)
- path: Test\bin\Debug\BurnOutSharp_net5.0.zip
name: BurnOutSharp (.NET 5.0)
name: BurnOutSharp (.NET 5.0)
- path: Test\bin\Debug\BurnOutSharp_net6.0.zip
name: BurnOutSharp (.NET 6.0)