// Detect It Easy: detection rule file format
// Author: deadmau5 <deadmau5@tutanota.de>
// Updated: DosX (@DosX-dev)

init("protector", "Denuvo");

function detect(bShowType, bShowVersion, bShowOptions) {
    if (PE.isSectionNamePresent(".arch") || PE.isSectionNamePresent(".edata") || PE.isSectionNamePresent(".srdata") || PE.isSectionNamePresent(".xpdata") || PE.isSectionNamePresent(".xdata") || PE.isSectionNamePresent(".xtls")) {
        if (PE.is64()) {
            // Mad Max, Metal Gear Solid: TPP, Rise of the Tomb Raider
            if (PE.compareEP("51 52 41 50 41 51 4C 8D ?? ?? ?? ?? ?? 4C 8D ?? ?? ?? ?? ?? 4D 29 C1")) {
                sVersion = "v1.0";
                bDetected = true;
            }
            // Lords of the Fallen, Batman: AK, Just Cause 3, Sherlock Holmes: TdD, Tales of Berseria etc
            else if (PE.compareEP("48 8D 0D ?? ?? ?? ?? E9 ?? ?? ?? ??")) {
                sVersion = "v2.0a";
                bDetected = true;
            }
            // Yesterday Origins
            else if (PE.compareEP("48 89 ?? ?? ?? ?? ?? 48 89 ?? ?? ?? ?? ?? 4C 89 ?? ?? ?? ?? ?? 4C 89 ?? ?? ?? ?? ?? 48 83 FA 01")) {
                sVersion = "v2.0b";
                bDetected = true;
            }
            // Sniper Ghost Warrior 3 (beta), Dead Rising 4 (SteamStub-free)
            else if (PE.compareEP("?? ?? ?? ?? ?? ?? ?? ?? 4C 89 1C 24 49 89 E3")) {
                sVersion = "v3.0a";
                bDetected = true;
            }
            // Atomic Heart
            else if (PE.compareEP("48 8D 64 24 .. 50 51 52 80 3D .. .. .. .. .. 75 .. 48 8D 05 .. .. .. .. 48 8D 0D .. .. .. ..")) {
                sVersion = "v17.0"; // v17.0, what? How?
                bDetected = true;
            }
            // Train Sim World CSX Heavy Haul
            else if (PE.compareEP("4D 8D ?? ?? ?? ?? ?? ?? ?? ?? ?? 48 89 ?? ?? ?? ?? ?? 48 8D ?? ?? 48 89 ?? 48 89 ?? 48 89")) {
                sVersion = "v3.0b";
                bDetected = true;
            } else if (PE.findSignature(0, PE.getSize(), "64 65 6E 75 76 6F 5F 61 74 64 00 00 00 00 00 00") !== -1) {
                // Unknown version
                // sVersion = "v?";
                bDetected = true;
            }
            // Check if steam_api64.dll present
            if (PE.isLibraryPresent("steam_api64.dll")) {
                // Override additional info
                sOptions = "Steam";
                bDetected = true;
            }
            // Check if uplay_r1_loader64.dll present
            if (PE.isLibraryPresent("uplay_r1_loader64.dll")) {
                // Override additional info
                sOptions = "uPlay";
                bDetected = true;
            }
            // Check if Core/Activation64.dll present
            if (PE.isLibraryPresent("Core/Activation64.dll")) {
                // Override additional info
                sOptions = "Origin";
                bDetected = true;
            }
        } else {
            // Pro Evolution Soccer 2017, Champions of Anteria
            if (PE.compareEP("55 89 E5 8D ?? ?? ?? ?? ?? ?? E8 ?? ?? ?? ?? E8 ?? ?? ?? ?? E8 ?? ?? ?? ?? E8 ?? ?? ?? ??")) {
                sVersion = "v1.0";
                bDetected = true;
            }
            // Romance of 13 Kingdoms, 2Dark
            else if (PE.compareEP("8D ?? ?? ?? ?? ?? ?? 89 7C 24 04 89 E7")) {
                sVersion = "v2.0";
                bDetected = true;
            } else {
                sVersion = "v?";
            }
            // Check if steam_api64.dll present
            if (PE.isLibraryPresent("steam_api.dll")) {
                // Override additional info
                sOptions = "Steam";
                bDetected = true;
            }
            // Check if uplay_r1_loader.dll present
            if (PE.isLibraryPresent("uplay_r1_loader.dll")) {
                // Override additional info
                sOptions = "uPlay";
                bDetected = true;
            }
            // Check if Core/Activation.dll present
            if (PE.isLibraryPresent("Core/Activation.dll")) {
                // Override additional info
                sOptions = "Origin";
                bDetected = true;
            }
        }
    }
    return result(bShowType, bShowVersion, bShowOptions);
}