using System; using System.IO; using UnityAntiModLoader.Models; namespace UnityAntiModLoader.Detectors { public static class MelonLoaderDetector { // Known MelonLoader directory structures private static readonly string[] s_KnownDirectories = new string[] { "MelonLoader", "MelonLoader/Dependencies", "MelonLoader/Managed", "MelonLoader/Libs", "Mods", "Plugins", "UserLibs", "UserData" }; // Known MelonLoader binaries, proxies, and logfiles private static readonly string[] s_KnownFiles = new string[] { "version.dll", "winmm.dll", "MelonLoader/MelonLoader.dll", "MelonLoader/Dependencies/Bootstrap.dll", "MelonLoader/Dependencies/Harmony/0Harmony.dll", "MelonLoader/Dependencies/Il2CppAssemblyGenerator/Il2CppAssemblyGenerator.dll", "MelonLoader/Dependencies/Mono.Cecil.dll", "MelonLoader/Latest.log" }; /// /// Scans the game directory for MelonLoader 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 = "MelonLoader", DetectionTimestamp = DateTime.UtcNow }; if (string.IsNullOrEmpty(gameRootDirectory) || !Directory.Exists(gameRootDirectory)) { return result; } // 1. Check for known MelonLoader 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 MelonLoader files & bootstrap hooks 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; } } }