diff --git a/BurnOutSharp/ProtectionType/SecuROM.cs b/BurnOutSharp/ProtectionType/SecuROM.cs
index e9ac6f01..9014ec0d 100644
--- a/BurnOutSharp/ProtectionType/SecuROM.cs
+++ b/BurnOutSharp/ProtectionType/SecuROM.cs
@@ -1,7 +1,9 @@
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
+using System.Linq;
using System.Text;
+using BurnOutSharp.ExecutableType.Microsoft;
using BurnOutSharp.Matching;
using BurnOutSharp.Tools;
@@ -10,53 +12,106 @@ namespace BurnOutSharp.ProtectionType
public class SecuROM : IContentCheck, IPathCheck
{
///
- public List GetContentMatchSets()
- {
- return new List
- {
- // AddD + (char)0x03 + (char)0x00 + (char)0x00 + (char)0x00)
- new ContentMatchSet(new byte?[] { 0x41, 0x64, 0x64, 0x44, 0x03, 0x00, 0x00, 0x00 }, GetV4Version, "SecuROM"),
-
- // (char)0xCA + (char)0xDD + (char)0xDD + (char)0xAC + (char)0x03
- new ContentMatchSet(new byte?[] { 0xCA, 0xDD, 0xDD, 0xAC, 0x03 }, GetV5Version, "SecuROM"),
-
- // .securom + (char)0xE0 + (char)0xC0
- new ContentMatchSet(new byte?[]
- {
- 0x2E, 0x73, 0x65, 0x63, 0x75, 0x72, 0x6F, 0x6D,
- 0xE0, 0xC0
- }, GetV7Version, "SecuROM"),
-
- // .securom
- new ContentMatchSet(new byte?[] { 0x2E, 0x73, 0x65, 0x63, 0x75, 0x72, 0x6F, 0x6D }, GetV7Version, "SecuROM"),
-
- // _and_play.dll + (char)0x00 + drm_pagui_doit
- new ContentMatchSet(new byte?[]
- {
- 0x5F, 0x61, 0x6E, 0x64, 0x5F, 0x70, 0x6C, 0x61,
- 0x79, 0x2E, 0x64, 0x6C, 0x6C, 0x00, 0x64, 0x72,
- 0x6D, 0x5F, 0x70, 0x61, 0x67, 0x75, 0x69, 0x5F,
- 0x64, 0x6F, 0x69, 0x74
- }, Utilities.GetFileVersion, "SecuROM Product Activation"),
-
- // 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
- new ContentMatchSet(new byte?[]
- {
- 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"),
-
- // .cms_t + (char)0x00
- new ContentMatchSet(new byte?[] { 0x2E, 0x63, 0x6D, 0x73, 0x5F, 0x74, 0x00 }, "SecuROM 1-3"),
-
- // .cms_d + (char)0x00
- new ContentMatchSet(new byte?[] { 0x2E, 0x63, 0x6D, 0x73, 0x5F, 0x64, 0x00 }, "SecuROM 1-3"),
- };
- }
+ public List GetContentMatchSets() => null;
///
- public string CheckContents(string file, byte[] fileContent, bool includeDebug = false) => null;
+ public string CheckContents(string file, byte[] fileContent, bool includeDebug = false)
+ {
+ // 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 .securom section, if it exists
+ var securomSection = sections.FirstOrDefault(s => Encoding.ASCII.GetString(s.Name).StartsWith(".securom"));
+ if (securomSection != null)
+ return $"SecuROM {GetV7Version(fileContent)}";
+
+ // Search after the last section
+ var lastSection = sections.LastOrDefault();
+ if (lastSection != null)
+ {
+ int sectionAddr = (int)lastSection.PointerToRawData;
+ int sectionEnd = sectionAddr + (int)lastSection.VirtualSize;
+ var matchers = new List
+ {
+ // AddD + (char)0x03 + (char)0x00 + (char)0x00 + (char)0x00)
+ new ContentMatchSet(
+ new ContentMatch(new byte?[] { 0x41, 0x64, 0x64, 0x44, 0x03, 0x00, 0x00, 0x00 }, start: sectionEnd),
+ GetV4Version, "SecuROM"),
+ };
+
+ string match = MatchUtil.GetFirstMatch(file, fileContent, matchers, includeDebug);
+ if (!string.IsNullOrWhiteSpace(match))
+ return match;
+ }
+
+ // Get the sections 5+, if they exist (example names: .fmqyrx, .vcltz, .iywiak)
+ for (int i = 4; i < sections.Length; i++)
+ {
+ var nthSection = sections[i];
+ string nthSectionName = Encoding.ASCII.GetString(nthSection.Name).Trim('\0');
+ if (nthSection != null && nthSectionName != ".idata" && nthSectionName != ".rsrc")
+ {
+ int sectionAddr = (int)nthSection.PointerToRawData;
+ int sectionEnd = sectionAddr + (int)nthSection.VirtualSize;
+ var matchers = new List
+ {
+ // (char)0xCA + (char)0xDD + (char)0xDD + (char)0xAC + (char)0x03
+ new ContentMatchSet(
+ new ContentMatch(new byte?[] { 0xCA, 0xDD, 0xDD, 0xAC, 0x03 }, start: sectionAddr, end: sectionEnd),
+ GetV5Version, "SecuROM"),
+ };
+
+ string match = MatchUtil.GetFirstMatch(file, fileContent, matchers, includeDebug);
+ if (!string.IsNullOrWhiteSpace(match))
+ return match;
+ }
+ }
+
+ // Get the .rdata section, if it exists
+ var rdataSection = sections.FirstOrDefault(s => Encoding.ASCII.GetString(s.Name).StartsWith(".rdata"));
+ if (rdataSection != null)
+ {
+ int sectionAddr = (int)rdataSection.PointerToRawData;
+ int sectionEnd = sectionAddr + (int)rdataSection.VirtualSize;
+ var matchers = new List
+ {
+ // drm_pagui_doit -- shortened from "_and_play.dll + (char)0x00 + drm_pagui_doit"
+ new ContentMatchSet(
+ new ContentMatch(new byte?[]
+ {
+ 0x64, 0x72, 0x6D, 0x5F, 0x70, 0x61, 0x67, 0x75,
+ 0x69, 0x5F, 0x64, 0x6F, 0x69, 0x74
+ }, start: sectionAddr, end: sectionEnd),
+ Utilities.GetFileVersion, "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
+ // new ContentMatchSet(
+ // new ContentMatch(new byte?[]
+ // {
+ // 0x53, 0x00, 0x65, 0x00, 0x63, 0x00, 0x75, 0x00,
+ // 0x52, 0x00, 0x4F, 0x00, 0x4D, 0x00, 0x20, 0x00,
+ // 0x50, 0x00, 0x41, 0x00
+ // }, start: sectionAddr, end: sectionEnd),
+ // Utilities.GetFileVersion, "SecuROM Product Activation"),
+ };
+
+ string match = MatchUtil.GetFirstMatch(file, fileContent, matchers, includeDebug);
+ if (!string.IsNullOrWhiteSpace(match))
+ return match;
+ }
+
+ // Get the .cms_d and .cms_t sections, if they exist -- TODO: Confirm if both are needed or either/or is fine
+ var cmsdSection = sections.FirstOrDefault(s => Encoding.ASCII.GetString(s.Name).StartsWith(".cms_d"));
+ var cmstSection = sections.FirstOrDefault(s => Encoding.ASCII.GetString(s.Name).StartsWith(".cms_t"));
+ if (cmsdSection != null || cmstSection != null)
+ return $"SecuROM 1-3";
+
+ return null;
+ }
///
public ConcurrentQueue CheckDirectoryPath(string path, IEnumerable files)
@@ -151,7 +206,7 @@ namespace BurnOutSharp.ProtectionType
return $"{version}.{subVersion[0]}{subVersion[1]}.{subSubVersion[0]}{subSubVersion[1]}.{subSubSubVersion[0]}{subSubSubVersion[1]}{subSubSubVersion[2]}{subSubSubVersion[3]}";
}
- public static string GetV7Version(string file, byte[] fileContent, List positions)
+ private static string GetV7Version(byte[] fileContent)
{
int index = 236;
byte[] bytes = new ReadOnlySpan(fileContent, index, 4).ToArray();