• Hello
Search Results for

    Show / Hide Table of Contents

    Desktop - Debugger - Detector (Pro)

    Debuggers let an attacker pause your game, inspect memory, change values, and step through your code. There are two flavours: user-mode debuggers attached to your process (e.g. Visual Studio, dnSpy, x64dbg, OllyDbg, JetBrains debugger) and kernel-mode debuggers attached to the system (e.g. WinDbg in /KD mode, Syser, SoftICE). Use the 'DebuggerDetector' to detect both and react accordingly.

    Detector

    The 'DebuggerDetector' does not require any monitor. On demand, it queries multiple debugger sources and aggregates the results:

    1. Managed debugger: Reads 'System.Diagnostics.Debugger.IsAttached' to detect a managed debugger like the Unity Editor debugger or the Visual Studio managed debugger.

    2. User-mode debugger: Asks the platform-specific 'IPlatformProbe.IsUserModeDebuggerPresent'. On Windows this combines 'kernel32!IsDebuggerPresent', 'kernel32!CheckRemoteDebuggerPresent', and 'ntdll!NtQueryInformationProcess' against 'ProcessDebugPort', 'ProcessDebugObjectHandle', and 'ProcessDebugFlags'. On macOS it inspects the 'P_TRACED' flag returned by 'sysctl' with 'KERN_PROC_PID'. On Linux it parses 'TracerPid' from '/proc/self/status'.

    3. Kernel-mode debugger: Asks the platform-specific 'IPlatformProbe.IsKernelModeDebuggerPresent'. On Windows this calls 'ntdll!NtQuerySystemInformation' with 'SystemKernelDebuggerInformation' and reports a kernel debugger that is enabled and present. On macOS and Linux, kernel-mode debugger detection is currently a no-op and reserved for a future native plugin probe.

    Observed Subject

    The detector does not observe any monitor. It runs an on-demand scan when 'ManualScan()' is invoked or, if enabled, automatically during 'Start' and on a configurable interval.

    Status

    When a debugger is found, the detector notifies its observers with a DesktopCheatingDetectionStatus, which implements IDesktopCheatingDetectionStatus (and therefore IDetectorStatus):

    public struct DesktopCheatingDetectionStatus : IDesktopCheatingDetectionStatus
    {
        // Probability that the detection is a false positive, in the range [0.0, 1.0].
        public float PossibilityOfFalsePositive { get; }
    
        // The threat rating reported with this detection.
        public uint ThreatRating { get; }
    
        // The type of cheating detected on the desktop platform.
        public EDesktopCheatingType DesktopCheatingType { get; }
    
        // A short, human-readable string describing what triggered the detection.
        public string Evidence { get; }
    }
    
    • Evidence: For example IsDebuggerPresent, ProcessDebugPort=0x..., KernelDebuggerEnabled, or Debugger.IsAttached.

    For this detector, DesktopCheatingType can be:

    public enum EDesktopCheatingType : byte
    {
        DEBUGGER_USER_MODE = 20,   // A user-mode debugger is attached to the process.
        DEBUGGER_KERNEL_MODE = 21, // A kernel-mode debugger is active on the system.
        DEBUGGER_REMOTE = 22       // A remote debugger is attached / a debug port is assigned.
    }
    

    Threat rating and false positives

    User mode and kernel mode evidence carry separate ratings, because a kernel debugger on a player machine is far more suspicious than a managed debugger attached during development. ThreatRating reports the larger of the two configured ratings.

    • Possibility Of False Positive User Mode: default 0.05 (range 0-1).
    • Possibility Of False Positive Kernel Mode: default 0.001 (range 0-1).
    • Threat Rating User Mode: default 400 (recommended 400).
    • Threat Rating Kernel Mode: default 750 (recommended 750).

    Each kind (user mode / kernel mode) is reported only once per game session to avoid spamming the punisher chain.

    Configuration

    • Is Active (isActive, bool, default true) - whether the detector is active and watching.
    • Possibility Of False Positive User Mode (possibilityOfFalsePositiveUserMode, float, default 0.05, range 0-1).
    • Possibility Of False Positive Kernel Mode (possibilityOfFalsePositiveKernelMode, float, default 0.001, range 0-1).
    • Threat Rating User Mode (threatRatingUserMode, uint, default 400).
    • Threat Rating Kernel Mode (threatRatingKernelMode, uint, default 750).
    • On Cheating Detection Event (OnCheatingDetectionEvent) - a UnityEvent raised on every detection.
    • Check Only On Game Start (CheckOnlyOnGameStart, bool, default false) - run the check only once on start; disable to also run a periodic recheck. Recommended false, because a debugger can attach at any time.
    • Recheck Interval For Possible Cheating (RecheckIntervalForPossibleCheating, float, default 5, range 0.1-600) - interval in seconds between checks.

    The individual user-mode / kernel-mode toggles and the "report managed-only" option are configured in the global project settings (see 'Configure Desktop Settings' below).

    Supported Platforms

    The detector is available on Windows, macOS, and Linux Standalone players.

    • User-mode debugger detection is implemented on all three platforms.
    • Kernel-mode debugger detection is currently implemented on Windows only; on macOS and Linux the kernel-mode probe returns false and is reserved for a future native plugin.

    Requirements

    There are no native requirements; the detector uses managed APIs and platform P/Invokes provided by the package. In the Unity Editor and in Development Builds, the detector only runs when 'Desktop_Enable_Development' is enabled in the global AntiCheat settings - this is important because the Unity Editor itself counts as a managed debugger.

    How To Use

    The usage is straightforward: attach a 'DebuggerDetector' to a child GameObject of the 'AntiCheat-Monitor', configure the global Desktop settings, and define a reaction to detected cheating.

    Requirements

    There are none. No additional monitor is required.

    Add Detector Component

    Manual

    Add the 'DebuggerDetector' MonoBehavior from the 'GUPS.AntiCheat.Detector.Desktop' namespace to your 'AntiCheat-Monitor' GameObject, or better, to a child GameObject.

    Add the 'DebuggerDetector' as a Component.

    Settings

    After attaching the 'DebuggerDetector' MonoBehavior to a GameObject, you will see the following in the inspector:

    The settings of the 'DebuggerDetector' Component (shown together with the 'VirtualEnvironmentDetector').

    • General Settings: Define here whether the detector should be active.
    • Threat Rating Settings: Define here the severity of the detected cheating (separate user-mode and kernel-mode ratings).
    • Observable Settings: Add here callbacks invoked when cheating is detected.
    • Debugger Settings: Set whether the scan runs once on Start and/or repeats on a configurable interval.

    Runtime

    On Start (and on the configured interval), the detector queries the managed and native debugger sources and notifies observers if a debugger is found. You can also trigger 'ManualScan()' yourself.

    Configure Desktop Settings

    Open 'Edit -> Project Settings -> GuardingPearSoftware -> AntiCheat' and switch to the 'Desktop' tab.

    In the AntiCheat Project Settings, configure the Desktop debugger detection.

    Use the following entries to control this detector:

    • Enable in Development: 'Desktop_Enable_Development'. Set to true to allow detection inside the Unity Editor and Development Builds. Off by default - keep this off in production-like testing or you will permanently report a debugger.
    • Detect User-Mode Debugger: 'Desktop_DetectUserModeDebugger'. Master switch for the user-mode probe. On by default.
    • Detect Kernel-Mode Debugger: 'Desktop_DetectKernelModeDebugger'. Master switch for the kernel-mode probe. On by default; effective only on Windows for now.
    • Report Managed Debugger Only: 'Desktop_Debugger_ReportManagedOnly'. When true, the detector only reports if 'Debugger.IsAttached' is true and ignores the native probes. Useful when shipping a Development Build to your QA team.

    Consume the detection in code

    Besides the inspector event, you can subscribe your own observer. Every detector derives from ADetector and exposes Subscribe(IObserver<IDetectorStatus>), which returns an IDisposable you can dispose to unsubscribe. Cast the status to DesktopCheatingDetectionStatus to read the desktop-specific fields:

    using System;
    using GUPS.AntiCheat;
    using GUPS.AntiCheat.Core.Detector;
    using GUPS.AntiCheat.Detector.Desktop;
    using UnityEngine;
    
    public class DebuggerDetectionLogger : MonoBehaviour, IObserver<IDetectorStatus>
    {
        private void Start()
        {
            var detector = AntiCheatMonitor.Instance.GetDetector<DebuggerDetector>();
            detector.Subscribe(this);
        }
    
        public void OnNext(IDetectorStatus status)
        {
            if (status is DesktopCheatingDetectionStatus desktopStatus)
            {
                Debug.LogWarning($"Debugger detected: {desktopStatus.DesktopCheatingType} " +
                                 $"(threat={desktopStatus.ThreatRating}, evidence={desktopStatus.Evidence}).");
            }
        }
    
        public void OnError(Exception error) { }
        public void OnCompleted() { }
    }
    

    React On Cheating

    When the detector is set up, you surely want to react to detected cheating.

    Punisher

    In general, any cheat detected is forwarded to the 'AntiCheat-Monitor', which calculates an overall threat level. Based on the threat level, you can apply punishments by using Punisher components added to a child GameObject of the 'AntiCheat-Monitor'. There are some built-in punishers that you can find here as prefabs:

    The location of the built-in Punisher prefabs.

    Inspector

    You can set a callback in the Unity Inspector view of the detector. This callback is invoked as soon as the specific cheating is detected.

    Code

    If you would like to write a custom listener for the detector, you can attach an observer:

    // Get the detector.
    var detector = AntiCheatMonitor.Instance
          .GetDetector<DebuggerDetector>();
    
    // Subscribe as observer and get notified on inconsistency.
    detector.Subscribe(myObserver);
    

    The detector also has an inherited property 'PossibleCheatingDetected' which is set to true once cheating has been detected.

    In This Article
    Back to top GuardingPearSoftware documentation