mirror of
https://github.com/SabreTools/BinaryObjectScanner.git
synced 2026-09-22 23:05:03 +00:00
Convert ProtectDisc to section based
This commit is contained in:
@@ -1,314 +1,200 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using BurnOutSharp.ExecutableType.Microsoft;
|
||||
using BurnOutSharp.Matching;
|
||||
using BurnOutSharp.Tools;
|
||||
|
||||
namespace BurnOutSharp.ProtectionType
|
||||
{
|
||||
public class ProtectDisc : IContentCheck
|
||||
// TODO: Investigate the connection between this and VOB Protect CD/DVD
|
||||
public class ProtectDISC : IContentCheck
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
public List<ContentMatchSet> GetContentMatchSets()
|
||||
{
|
||||
return new List<ContentMatchSet>
|
||||
{
|
||||
// HúMETINF
|
||||
new ContentMatchSet(new byte?[] { 0x48, 0xFA, 0x4D, 0x45, 0x54, 0x49, 0x4E, 0x46 }, GetVersion76till10, "ProtectDisc"),
|
||||
|
||||
// ACE-PCD
|
||||
new ContentMatchSet(new byte?[] { 0x41, 0x43, 0x45, 0x2D, 0x50, 0x43, 0x44 }, GetVersion6till8, "ProtectDisc"),
|
||||
};
|
||||
}
|
||||
public List<ContentMatchSet> GetContentMatchSets() => null;
|
||||
|
||||
/// <inheritdoc/>
|
||||
public string CheckContents(string file, byte[] fileContent, bool includeDebug = false) => null;
|
||||
|
||||
public static string GetVersion6till8(string file, byte[] fileContent, List<int> positions)
|
||||
public string CheckContents(string file, byte[] fileContent, bool includeDebug = false)
|
||||
{
|
||||
string version = SearchProtectDiscVersion(file, fileContent);
|
||||
if (version.Length > 0)
|
||||
// Get the sections from the executable, if possible
|
||||
PortableExecutable pex = PortableExecutable.Deserialize(fileContent, 0);
|
||||
var sections = pex?.SectionTable;
|
||||
if (sections == null)
|
||||
return null;
|
||||
|
||||
// Get the 4th section, if it exists (example names: ACE4)
|
||||
var fourthSection = sections.Length < 4 ? null : sections[3];
|
||||
if (fourthSection != null)
|
||||
{
|
||||
string[] astrVersionArray = version.Split('.');
|
||||
return $"{astrVersionArray[0]}.{astrVersionArray[1]}.{astrVersionArray[2]} (Build {astrVersionArray[3]})";
|
||||
int sectionAddr = (int)fourthSection.PointerToRawData;
|
||||
int sectionEnd = sectionAddr + (int)fourthSection.VirtualSize;
|
||||
var matchers = new List<ContentMatchSet>
|
||||
{
|
||||
// ACE-PCD
|
||||
new ContentMatchSet(
|
||||
new ContentMatch(new byte?[] { 0x41, 0x43, 0x45, 0x2D, 0x50, 0x43, 0x44 }, start: sectionAddr, end: sectionEnd),
|
||||
GetVersion6till8, "ProtectDISC"),
|
||||
};
|
||||
|
||||
string match = MatchUtil.GetFirstMatch(file, fileContent, matchers, includeDebug);
|
||||
if (!string.IsNullOrWhiteSpace(match))
|
||||
return match;
|
||||
}
|
||||
|
||||
return $"{GetVersionBuild6till8(fileContent, positions[0])}";
|
||||
}
|
||||
|
||||
public static string GetVersion76till10(string file, byte[] fileContent, List<int> positions)
|
||||
{
|
||||
string version = SearchProtectDiscVersion(file, fileContent);
|
||||
if (version.Length > 0)
|
||||
// Get the last section (example names: ACE5, akxpxgcv, and piofinqb)
|
||||
var lastSection = sections.LastOrDefault();
|
||||
if (lastSection != null)
|
||||
{
|
||||
string[] astrVersionArray = version.Split('.');
|
||||
if (astrVersionArray[0] == "9")
|
||||
int sectionAddr = (int)lastSection.PointerToRawData;
|
||||
int sectionEnd = sectionAddr + (int)lastSection.VirtualSize;
|
||||
var matchers = new List<ContentMatchSet>
|
||||
{
|
||||
if (GetVersionBuild76till10(fileContent, positions[0], out int ibuild).Length > 0)
|
||||
return $"{astrVersionArray[0]}.{astrVersionArray[1]}{astrVersionArray[2]}.{astrVersionArray[3]} (Build {ibuild})";
|
||||
}
|
||||
else
|
||||
{
|
||||
return $"{astrVersionArray[0]}.{astrVersionArray[1]}.{astrVersionArray[2]} (Build {astrVersionArray[3]})";
|
||||
}
|
||||
// HúMETINF
|
||||
new ContentMatchSet(
|
||||
new ContentMatch(new byte?[] { 0x48, 0xFA, 0x4D, 0x45, 0x54, 0x49, 0x4E, 0x46 }, start: sectionAddr, end: sectionEnd),
|
||||
GetVersion76till10, "ProtectDISC"),
|
||||
};
|
||||
|
||||
string match = MatchUtil.GetFirstMatch(file, fileContent, matchers, includeDebug);
|
||||
if (!string.IsNullOrWhiteSpace(match))
|
||||
return match;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private static string GetVersionBuild6till8(byte[] fileContent, int position)
|
||||
public static string GetVersion6till8(string file, byte[] fileContent, List<int> positions)
|
||||
{
|
||||
string version;
|
||||
string strBuild;
|
||||
string version, strBuild = string.Empty;
|
||||
int index = positions[0] - 12;
|
||||
|
||||
int index = position - 12;
|
||||
if (new ArraySegment<byte>(fileContent, index, 4).SequenceEqual(new byte[] { 0x0A, 0x0D, 0x0A, 0x0D })) // ProtectDisc 6-7 with Build Number in plain text
|
||||
// Version 6-7 with Build Number in plain text
|
||||
if (new ArraySegment<byte>(fileContent, index, 4).SequenceEqual(new byte[] { 0x0A, 0x0D, 0x0A, 0x0D }))
|
||||
{
|
||||
index = position - 12 - 6;
|
||||
index = positions[0] - 12 - 6;
|
||||
|
||||
// ProtectDisc 7
|
||||
// Version 7
|
||||
if (new string(new ArraySegment<byte>(fileContent, index, 6).Select(b => (char)b).ToArray()) == "Henrik")
|
||||
{
|
||||
version = "7.1-7.5";
|
||||
index = position - 12 - 6 - 6;
|
||||
index = positions[0] - 12 - 6 - 6;
|
||||
}
|
||||
|
||||
// ProtectDisc 6
|
||||
// Version 6
|
||||
else
|
||||
{
|
||||
// TODO: Figure out if the version can be more granular
|
||||
version = "6";
|
||||
index = position - 12 - 10;
|
||||
index = positions[0] - 12 - 10;
|
||||
while (true) //search for e.g. "Build 050913 - September 2005"
|
||||
{
|
||||
if (Char.IsNumber((char)fileContent[index]))
|
||||
break;
|
||||
|
||||
index -= 1; //search upwards
|
||||
index--; // Search upwards
|
||||
}
|
||||
|
||||
index -= 5;
|
||||
}
|
||||
|
||||
char[] arrBuild = new ArraySegment<byte>(fileContent, index, 6).Select(b => (char)b).ToArray();
|
||||
if (!Int32.TryParse(new string(arrBuild), out int intBuild))
|
||||
strBuild = $"[Build {new string(arrBuild).Trim()}]";
|
||||
else
|
||||
strBuild = $"[Build 0x{intBuild:X} / {intBuild}]";
|
||||
|
||||
return $"{version} {strBuild}".Trim();
|
||||
}
|
||||
else
|
||||
{
|
||||
index = position + 28;
|
||||
index = positions[0] + 28;
|
||||
if (fileContent[index] == 0xFB)
|
||||
return "7.6-7.x";
|
||||
else
|
||||
return "8.0";
|
||||
}
|
||||
|
||||
strBuild = new string(new ArraySegment<byte>(fileContent, index, 5).Select(b => (char)b).ToArray());
|
||||
return $"{version} (Build {strBuild})";
|
||||
}
|
||||
|
||||
private static string GetVersionBuild76till10(byte[] fileContent, int position, out int irefBuild)
|
||||
public static string GetVersion76till10(string file, byte[] fileContent, List<int> positions)
|
||||
{
|
||||
int index = position + 37;
|
||||
int index = positions[0] + 37;
|
||||
byte subversion = fileContent[index];
|
||||
index++;
|
||||
index++;
|
||||
index += 2;
|
||||
byte version = fileContent[index];
|
||||
index = position + 49;
|
||||
irefBuild = BitConverter.ToInt32(fileContent, index);
|
||||
index = position + 53;
|
||||
index = positions[0] + 49;
|
||||
int irefBuild = BitConverter.ToInt32(fileContent, index);
|
||||
index = positions[0] + 53;
|
||||
byte versionindicatorPD9 = fileContent[index];
|
||||
index = position + 0x40;
|
||||
index = positions[0] + 0x40;
|
||||
byte subsubversionPD9x = fileContent[index];
|
||||
index++;
|
||||
byte subversionPD9x2 = fileContent[index];
|
||||
index++;
|
||||
byte subversionPD9x1 = fileContent[index];
|
||||
|
||||
// version 7
|
||||
// Version 7
|
||||
if (version == 0xAC)
|
||||
return $"7.{subversion ^ 0x43} (Build {irefBuild})";
|
||||
{
|
||||
// TODO: Figure out if the version can be more granular
|
||||
return $"7.{subversion ^ 0x43} [Build 0x{irefBuild:X} / {irefBuild}]";
|
||||
}
|
||||
|
||||
// version 8
|
||||
// Version 8
|
||||
else if (version == 0xA2)
|
||||
{
|
||||
if (subversion == 0x46)
|
||||
{
|
||||
if ((irefBuild & 0x3A00) == 0x3A00)
|
||||
return $"8.2 (Build {irefBuild})";
|
||||
return $"8.2 [Build 0x{irefBuild:X} / {irefBuild}]";
|
||||
else
|
||||
return $"8.1 (Build {irefBuild})";
|
||||
return $"8.1 [Build 0x{irefBuild:X} / {irefBuild}]";
|
||||
}
|
||||
|
||||
return $"8.{subversion ^ 0x47} (Build {irefBuild})";
|
||||
// TODO: Figure out if the version can be more granular
|
||||
return $"8.{subversion ^ 0x47} [Build 0x{irefBuild:X} / {irefBuild}]";
|
||||
}
|
||||
|
||||
// version 9
|
||||
// Version 9
|
||||
else if (version == 0xA3)
|
||||
{
|
||||
// version removed or not given
|
||||
// Version removed or not given
|
||||
if ((subversionPD9x2 == 0x5F && subversionPD9x1 == 0x61) || (subversionPD9x1 == 0 && subversionPD9x2 == 0))
|
||||
{
|
||||
if (versionindicatorPD9 == 0xB)
|
||||
{
|
||||
return $"9.0-9.4 (Build {irefBuild})";
|
||||
return $"9.0-9.4 [Build 0x{irefBuild:X} / {irefBuild}]";
|
||||
}
|
||||
else if (versionindicatorPD9 == 0xC)
|
||||
{
|
||||
// TODO: Figure out if the version can be more granular
|
||||
if (subversionPD9x2 == 0x5F && subversionPD9x1 == 0x61)
|
||||
return $"9.5-9.11 (Build {irefBuild})";
|
||||
return $"9.5-9.11 [Build 0x{irefBuild:X} / {irefBuild}]";
|
||||
else if (subversionPD9x1 == 0 && subversionPD9x2 == 0)
|
||||
return $"9.11-9.20 (Build {irefBuild})";
|
||||
}
|
||||
else
|
||||
{
|
||||
return $"9.{subversionPD9x1}{subversionPD9x2}.{subsubversionPD9x} (Build {irefBuild})";
|
||||
return $"9.11-9.20 [Build 0x{irefBuild:X} / {irefBuild}]";
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return $"9.{subversionPD9x1}{subversionPD9x2}.{subsubversionPD9x} [Build 0x{irefBuild:X} / {irefBuild}]";
|
||||
}
|
||||
}
|
||||
|
||||
// version 10
|
||||
// Version 10
|
||||
else if (version == 0xA0)
|
||||
{
|
||||
// version removed
|
||||
// Version removed -- TODO: Figure out if the version can be more granular
|
||||
if (subversionPD9x1 != 0 || subversionPD9x2 != 0)
|
||||
return $"10.{subversionPD9x1}.{subsubversionPD9x} (Build {irefBuild})";
|
||||
return $"10.{subversionPD9x1}.{subsubversionPD9x} [Build 0x{irefBuild:X} / {irefBuild}]";
|
||||
else
|
||||
return $"10.x (Build {irefBuild})";
|
||||
return $"10.x [Build 0x{irefBuild:X} / {irefBuild}]";
|
||||
}
|
||||
|
||||
// unknown version
|
||||
// Unknown version
|
||||
else
|
||||
{
|
||||
return $"7.6-10.x (Build {irefBuild})";
|
||||
return $"7.6-10.x [Build 0x{irefBuild:X} / {irefBuild}]";
|
||||
}
|
||||
|
||||
return string.Empty;
|
||||
}
|
||||
|
||||
// TODO: Analyze this method and figure out if this can be done without attempting execution
|
||||
private static string SearchProtectDiscVersion(string file, byte[] fileContent)
|
||||
{
|
||||
// If the file isn't executable, don't even bother
|
||||
if (!EVORE.IsPEExecutable(fileContent))
|
||||
return string.Empty;
|
||||
|
||||
// Get some of the required paths
|
||||
string tempexe = EVORE.MakeTempFile(fileContent);
|
||||
string[] dependentDlls = EVORE.CopyDependentDlls(file, fileContent);
|
||||
string pdPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "ProtectDisc");
|
||||
|
||||
// Clean up any temp files before attempting to run
|
||||
Utilities.SafeTempDelete("a*.tmp");
|
||||
Utilities.SafeTempDelete("PCD*.sys");
|
||||
if (Directory.Exists(pdPath))
|
||||
Utilities.SafeDelete(Path.Combine(pdPath, "p*.dll"));
|
||||
|
||||
// Try to safely start the temp executable
|
||||
Process exe = EVORE.StartSafe(tempexe);
|
||||
if (exe == null)
|
||||
return string.Empty;
|
||||
|
||||
string version = "";
|
||||
Process[] processes = new Process[0];
|
||||
DateTime timestart = DateTime.Now;
|
||||
do
|
||||
{
|
||||
exe.Refresh();
|
||||
string[] files = new string[0];
|
||||
|
||||
// Check for ProtectDisc 8.2-x
|
||||
if (Directory.Exists(pdPath))
|
||||
files = Directory.GetFiles(pdPath, "p*.dll");
|
||||
|
||||
if (files.Any())
|
||||
{
|
||||
string fileVersion = Utilities.GetFileVersion(files[0]);
|
||||
if (!string.IsNullOrWhiteSpace(fileVersion))
|
||||
{
|
||||
version = fileVersion;
|
||||
|
||||
// ProtectDisc 9 uses a ProtectDisc-Core dll version 8.0.x
|
||||
if (version.StartsWith("8.0"))
|
||||
version = string.Empty;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//check for ProtectDisc 7.1-8.1
|
||||
files = Directory.GetFiles(Path.GetTempPath(), "a*.tmp");
|
||||
if (files.Any())
|
||||
{
|
||||
string fileVersion = Utilities.GetFileVersion(files[0]);
|
||||
if (!string.IsNullOrWhiteSpace(fileVersion))
|
||||
{
|
||||
version = fileVersion;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (exe.HasExited)
|
||||
break;
|
||||
|
||||
processes = Process.GetProcessesByName(exe.ProcessName);
|
||||
if (processes.Length == 2)
|
||||
{
|
||||
processes[0].Refresh();
|
||||
processes[1].Refresh();
|
||||
if (processes[1].WorkingSet64 > exe.WorkingSet64)
|
||||
exe = processes[1];
|
||||
else if (processes[0].WorkingSet64 > exe.WorkingSet64) //else if (processes[0].Modules.Count > exe.Modules.Count)
|
||||
exe = processes[0];
|
||||
}
|
||||
} while (processes.Length > 0 && DateTime.Now.Subtract(timestart).TotalSeconds < 20);
|
||||
|
||||
Thread.Sleep(500);
|
||||
if (!exe.HasExited)
|
||||
{
|
||||
processes = Process.GetProcessesByName(exe.ProcessName);
|
||||
if (processes.Length == 2)
|
||||
{
|
||||
try
|
||||
{
|
||||
processes[0].Kill();
|
||||
}
|
||||
catch { }
|
||||
processes[0].Close();
|
||||
try
|
||||
{
|
||||
processes[1].Kill();
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
else
|
||||
{
|
||||
exe.Refresh();
|
||||
try
|
||||
{
|
||||
exe.Kill();
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
}
|
||||
|
||||
exe.Close();
|
||||
Thread.Sleep(500);
|
||||
|
||||
// Clean up any temp files after running
|
||||
Utilities.SafeDelete(tempexe);
|
||||
Utilities.SafeTempDelete("a*.tmp");
|
||||
Utilities.SafeTempDelete("PCD*.sys");
|
||||
if (Directory.Exists(pdPath))
|
||||
Utilities.SafeDelete(Path.Combine(pdPath, "p*.dll"));
|
||||
|
||||
if (dependentDlls != null)
|
||||
{
|
||||
foreach (string dll in dependentDlls)
|
||||
{
|
||||
Utilities.SafeDelete(dll);
|
||||
}
|
||||
}
|
||||
|
||||
return version;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user