using System; using System.IO; using UnityAntiModLoader.Models; namespace UnityAntiModLoader.Detectors { public static class BepInExDetector { // Known BepInEx directory structures private static readonly string[] s_KnownDirectories = new string[] { "BepInEx", "BepInEx/core", "BepInEx/plugins", "BepInEx/patchers", "BepInEx/config" }; // Known BepInEx binaries and proxy DLLs private static readonly string[] s_KnownFiles = new string[] { "doorstop_config.ini", "winhttp.dll", "doorstop_version.txt", "BepInEx/core/BepInEx.dll", "BepInEx/core/BepInEx.Core.dll", "BepInEx/core/0Harmony.dll", "BepInEx/core/0Harmony20.dll", "BepInEx/core/Mono.Cecil.dll", "BepInEx/core/BepInEx.Preloader.dll", "BepInEx/LogOutput.log" }; /// /// Scans the game directory for BepInEx mod loader artifacts. /// /// Base path of the game executable. /// ModDetectionResult with detected files and directories. public static ModDetectionResult Scan(string gameRootDirectory) { var result = new ModDetectionResult { FrameworkName = "BepInEx", DetectionTimestamp = DateTime.UtcNow }; if (string.IsNullOrEmpty(gameRootDirectory) || !Directory.Exists(gameRootDirectory)) { return result; } // 1. Check for known BepInEx directories foreach (string relDir in s_KnownDirectories) { string fullDirPath = Path.Combine(gameRootDirectory, relDir); try { if (Directory.Exists(fullDirPath)) { result.DetectedArtifacts.Add($"Directory: {relDir}"); } } catch { // Ignore filesystem access exceptions } } // 2. Check for known BepInEx files & proxy loaders foreach (string relFile in s_KnownFiles) { string fullFilePath = Path.Combine(gameRootDirectory, relFile); try { if (File.Exists(fullFilePath)) { result.DetectedArtifacts.Add($"File: {relFile}"); } } catch { // Ignore filesystem access exceptions } } // Evaluate severity if (result.DetectedArtifacts.Count > 0) { result.Severity = result.DetectedArtifacts.Count >= 2 ? DetectionSeverity.Critical : DetectionSeverity.High; } return result; } } }