diff --git a/BinaryObjectScanner.Test/Data/StaticChecksTests.cs b/BinaryObjectScanner.Test/Data/StaticChecksTests.cs
index 86208919..5a072dec 100644
--- a/BinaryObjectScanner.Test/Data/StaticChecksTests.cs
+++ b/BinaryObjectScanner.Test/Data/StaticChecksTests.cs
@@ -44,7 +44,7 @@ public void PathCheckClasses_Populated()
public void PortableExecutableCheckClasses_Populated()
{
var actual = StaticChecks.PortableExecutableCheckClasses;
- Assert.Equal(105, actual.Length);
+ Assert.Equal(106, actual.Length);
}
}
}
diff --git a/BinaryObjectScanner.Test/Protection/CEGTests.cs b/BinaryObjectScanner.Test/Protection/CEGTests.cs
new file mode 100644
index 00000000..d982649d
--- /dev/null
+++ b/BinaryObjectScanner.Test/Protection/CEGTests.cs
@@ -0,0 +1,22 @@
+using System.IO;
+using BinaryObjectScanner.Protection;
+using Xunit;
+
+namespace BinaryObjectScanner.Test.Protection
+{
+ public class CEGTests
+ {
+ [Fact]
+ public void CheckPortableExecutableTest()
+ {
+ string file = "filename";
+ SabreTools.Data.Models.PortableExecutable.Executable model = new();
+ Stream source = new MemoryStream(new byte[1024]);
+ SabreTools.Serialization.Wrappers.PortableExecutable exe = new(model, source);
+
+ var checker = new CenegaProtectDVD();
+ string? actual = checker.CheckExecutable(file, exe, includeDebug: false);
+ Assert.Null(actual);
+ }
+ }
+}
diff --git a/BinaryObjectScanner/Protection/CEG.Constants.cs b/BinaryObjectScanner/Protection/CEG.Constants.cs
new file mode 100644
index 00000000..50a1692c
--- /dev/null
+++ b/BinaryObjectScanner/Protection/CEG.Constants.cs
@@ -0,0 +1,63 @@
+using System.Collections.Generic;
+
+namespace BinaryObjectScanner.Protection
+{
+ public partial class CEG
+ {
+ ///
+ /// Dictionary of known CEG executables with compilation time as the key, and the string value as a combination
+ /// of depot ID, manifest version, and filename.
+ ///
+ /// Contained in a separate file since dictionary size will be very large.
+ private static readonly Dictionary CEGDictionary = new()
+ {
+ //{ 1298033762, "Shogun total war 2 demo test" },
+ { 1264170802, "10681 (v0-1) - AvP_DX11.exe" },
+ { 1264171199, "10681 (v0-1) - AvP.exe" },
+ { 1264759825, "10681 (v2) - AvP.exe" },
+ { 1264760178, "10681 (v2) - AvP_DX11.exe" },
+ { 1265104029, "10681 (v3) - AvP.exe" },
+ { 1265104767, "10681 (v3) - AvP_DX11.exe" },
+ { 1265196934, "10681 (v4) - AvP.exe" },
+ { 1265197111, "10681 (v4) - AvP_DX11.exe" },
+ { 1265200884, "10681 (v5) - AvP_DX11.exe" },
+ { 1265201120, "10681 (v5) - AvP.exe" },
+ { 1265218568, "10681 (v6) - AvP.exe" },
+ { 1265218748, "10681 (v6) - AvP_DX11.exe" },
+ { 1265626467, "10681 (v7) - AvP_DX11.exe" },
+ { 1265626733, "10681 (v7) - AvP.exe" },
+ { 1265639234, "10681 (v8) - AvP.exe" },
+ { 1265639459, "10681 (v8) - AvP_DX11.exe" },
+ { 1265711093, "10681 (v9) - AvP_DX11.exe" },
+ { 1265711343, "10681 (v9) - AvP.exe" },
+ { 1265729320, "10681 (v10-11) - AvP.exe" },
+ { 1265729583, "10681 (v10-11) - AvP_DX11.exe" },
+ { 1265898579, "10681 (v12) - AvP.exe" },
+ { 1265898814, "10681 (v12) - AvP_DX11.exe" },
+ { 1265910002, "10681 (v13) - AvP_DX11.exe" },
+ { 1265910166, "10681 (v13) - AvP.exe" },
+ { 1265973550, "10681 (v14) - AvP.exe" },
+ { 1265973915, "10681 (v14) - AvP_DX11.exe" },
+ { 1265992000, "10681 (v15) - AvP_DX11.exe" },
+ { 1265992237, "10681 (v15) - AvP.exe" },
+ { 1266001507, "10681 (v16) - AvP_DX11.exe" },
+ { 1266001711, "10681 (v16) - AvP.exe" },
+ { 1266254226, "10681 (v17) - AvP_DX11.exe" },
+ { 1266254418, "10681 (v17) - AvP.exe" },
+ { 1266280922, "10681 (v18-19) - AvP.exe" },
+ { 1266283570, "10681 (v18-19) - AvP_DX11.exe" },
+ { 1266338581, "10681 (v20) - AvP_DX11.exe" },
+ { 1266339302, "10681 (v20) - AvP.exe" },
+ { 1266493077, "10681 (v21) - AvP.exe" },
+ { 1266493275, "10681 (v21) - AvP_DX11.exe" },
+ { 1266593945, "10681 (v22) - AvP.exe" },
+ { 1266594188, "10681 (v22) - AvP_DX11.exe" },
+ { 1266799462, "10681 (v23) - AvP.exe" },
+ { 1266802085, "10681 (v23) - AvP_DX11.exe" },
+ { 1266863479, "10681 (v24) - AvP.exe" },
+ { 1266863657, "10681 (v24) - AvP_DX11.exe" },
+ { 1266927862, "10681 (v25) - AvP_DX11.exe" },
+ { 1266928166, "10681 (v25) - AvP.exe" },
+ };
+ }
+}
diff --git a/BinaryObjectScanner/Protection/CEG.cs b/BinaryObjectScanner/Protection/CEG.cs
new file mode 100644
index 00000000..479bd2f2
--- /dev/null
+++ b/BinaryObjectScanner/Protection/CEG.cs
@@ -0,0 +1,43 @@
+using BinaryObjectScanner.Interfaces;
+using SabreTools.Serialization.Wrappers;
+
+namespace BinaryObjectScanner.Protection
+{
+ ///
+ /// Protection that used to be offered by Valve for games on Steam. By default, protected executables are "stripped"
+ /// of varying 4KiB "strips", and these "strips" would only be downloaded when the user attempted to run the game on
+ /// Steam.
+ ///
+ public partial class CEG : IExecutableCheck
+ {
+ ///
+ public string? CheckExecutable(string file, PortableExecutable exe, bool includeDebug)
+ {
+ var strs = exe.GetFirstSectionStrings(".rdata");
+ if (strs is not null)
+ {
+ if (strs.Exists(s => s.Contains("STEAMSTART") && s.Contains("STEAM_DRM_IPC")))
+ {
+ if (strs.Exists(s => s.Contains("This file has been stripped")))
+ {
+ return "CEG - Stripped";
+ }
+ else if (strs.Exists(s => s.Contains("This file contains strips")))
+ {
+ // TODO: Will be uncommented in the future when the rest of the CEG samples can be obtained.
+ /*var value = CEGDictionary.TryGetValue(exe.COFFFileHeader.TimeDateStamp, out var gameName);
+ if (value)
+ {
+ return $"CEG - Contains Strips - {gameName}";
+ }*/
+ return "CEG - Contains Strips";
+ }
+
+ return "CEG - Could not determine whether executable contains strips, please report to us on GitHub!";
+ }
+ }
+
+ return null;
+ }
+ }
+}