diff --git a/BurnOutSharp/ProtectionType/Denuvo.cs b/BurnOutSharp/ProtectionType/Denuvo.cs new file mode 100644 index 00000000..037e2b1b --- /dev/null +++ b/BurnOutSharp/ProtectionType/Denuvo.cs @@ -0,0 +1,218 @@ +using System.Collections.Generic; +using BurnOutSharp.ExecutableType.Microsoft; +using BurnOutSharp.ExecutableType.Microsoft.PE; +using BurnOutSharp.Interfaces; +using BurnOutSharp.Matching; +using BurnOutSharp.Tools; + +namespace BurnOutSharp.ProtectionType +{ + // Data sourced from: + // 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 + public class Denuvo : IPortableExecutableCheck + { + /// + public string CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug) + { + // Get the sections from the executable, if possible + var sections = pex?.SectionTable; + if (sections == null) + return null; + + // 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.EntryPointRaw.StartsWith(denuvoProtector)) + return "Denuvo Protector"; + } + + // Denuvo + var timingMatchers = new List + { + // Denuvo Timing + new ContentMatchSet( + new byte?[] + { + 0x44, 0x65, 0x6E, 0x75, 0x76, 0x6F, 0x20, 0x54, + 0x69, 0x6D, 0x69, 0x6E, 0x67, + }, "Denuvo") + }; + + if (pex.ContainsSection(".arch") || pex.ContainsSection(".srdata") || !string.IsNullOrWhiteSpace(MatchUtil.GetFirstMatch(file, pex.EntryPointRaw, timingMatchers, includeDebug))) + { + if (pex.OptionalHeader.Magic == OptionalHeaderType.PE32Plus) + { + var matchers = new List + { + // 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)"), + + // 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)"), + + // 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)"), + + // 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)"), + + // 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)"), + }; + + string match = MatchUtil.GetFirstMatch(file, pex.EntryPointRaw, matchers, includeDebug); + if (!string.IsNullOrWhiteSpace(match)) + return match; + + 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 + { + // 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)"), + + // 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)"), + }; + + string match = MatchUtil.GetFirstMatch(file, pex.EntryPointRaw, matchers, includeDebug); + if (!string.IsNullOrWhiteSpace(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; + //} + } + } + + return null; + } + } +} diff --git a/README.md b/README.md index 1cf47e45..cea4faf2 100644 --- a/README.md +++ b/README.md @@ -40,6 +40,7 @@ Below is a list of protections detected by BurnOutSharp. The two columns explain | Cenga ProtectDVD | True | False | | | CodeLock / CodeLok / CopyLok | True | False | Partially unconfirmed² | | CopyKiller | True | True | Unconfirmed¹ | +| Denuvo | True | False | | | DiscGuard | False | True | Unconfirmed¹ | | DVD-Movie-PROTECT | False | True | Unconfirmed¹ | | DVD Crypt | False | True | Unconfirmed¹ |