Decompiled source of MLVScan v1.6.0

Plugins/MLVScan.MelonLoader.dll

Decompiled a week ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Resources;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Cryptography;
using System.Security.Permissions;
using System.Text;
using System.Text.RegularExpressions;
using MLVScan;
using MLVScan.Abstractions;
using MLVScan.Adapters;
using MLVScan.Models;
using MLVScan.Models.Rules;
using MLVScan.Services;
using MLVScan.Services.Helpers;
using MelonLoader;
using MelonLoader.Preferences;
using MelonLoader.Utils;
using Microsoft.CodeAnalysis;
using Mono.Cecil;
using Mono.Cecil.Cil;
using Mono.Collections.Generic;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: MelonInfo(typeof(Core), "MLVScan", "1.6.0", "Bars", null)]
[assembly: MelonPriority(int.MinValue)]
[assembly: MelonColor(255, 139, 0, 0)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("MLVScan.MelonLoader")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.6.0")]
[assembly: AssemblyInformationalVersion("1.0.0+580829955f1ad2ee1bc299a401e233e1572a9d1f")]
[assembly: AssemblyProduct("MLVScan.MelonLoader")]
[assembly: AssemblyTitle("MLVScan.MelonLoader")]
[assembly: NeutralResourcesLanguage("en-US")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.6.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace MLVScan
{
	public class Core : MelonPlugin
	{
		private ServiceFactory _serviceFactory;

		private ConfigManager _configManager;

		private ModScanner _modScanner;

		private ModDisabler _modDisabler;

		private IlDumpService _ilDumpService;

		private DeveloperReportGenerator _developerReportGenerator;

		private bool _initialized;

		private static readonly string[] DefaultWhitelistedHashes = new string[4] { "3918e1454e05de4dd3ace100d8f4d53936c9b93694dbff5bcc0293d689cb0ab7", "8e6dd1943c80e2d1472a9dc2c6722226d961027a7ec20aab9ad8f1184702d138", "d47eb6eabd3b6e3b742c7d9693651bc3a61a90dcbe838f9a4276953089ee4951", "cfe43c0d285867a5701d96de1edd25cb02725fe2629b88386351dc07b11a08b5" };

		public override void OnEarlyInitializeMelon()
		{
			try
			{
				((MelonBase)this).LoggerInstance.Msg("Pre-scanning for malicious mods...");
				_serviceFactory = new ServiceFactory(((MelonBase)this).LoggerInstance);
				_configManager = _serviceFactory.CreateConfigManager();
				InitializeDefaultWhitelist();
				_modScanner = _serviceFactory.CreateModScanner();
				_modDisabler = _serviceFactory.CreateModDisabler();
				_ilDumpService = _serviceFactory.CreateIlDumpService();
				_developerReportGenerator = _serviceFactory.CreateDeveloperReportGenerator();
				_initialized = true;
				ScanAndDisableMods(force: true);
			}
			catch (Exception ex)
			{
				((MelonBase)this).LoggerInstance.Error("Error in pre-mod scan: " + ex.Message);
				((MelonBase)this).LoggerInstance.Error(ex.StackTrace);
			}
		}

		public override void OnInitializeMelon()
		{
			try
			{
				((MelonBase)this).LoggerInstance.Msg("MLVScan initialization complete");
				if (_configManager.Config.WhitelistedHashes.Length != 0)
				{
					((MelonBase)this).LoggerInstance.Msg($"{_configManager.Config.WhitelistedHashes.Length} mod(s) are whitelisted and won't be scanned");
					((MelonBase)this).LoggerInstance.Msg("To manage whitelisted mods, edit MelonPreferences.cfg");
				}
			}
			catch (Exception ex)
			{
				((MelonBase)this).LoggerInstance.Error("Error initializing MLVScan: " + ex.Message);
				((MelonBase)this).LoggerInstance.Error(ex.StackTrace);
			}
		}

		private void InitializeDefaultWhitelist()
		{
			if (_configManager != null && _configManager.GetWhitelistedHashes().Length == 0)
			{
				((MelonBase)this).LoggerInstance.Msg("Initializing default whitelist");
				_configManager.SetWhitelistedHashes(DefaultWhitelistedHashes);
			}
		}

		public Dictionary<string, List<ScanFinding>> ScanAndDisableMods(bool force = false)
		{
			try
			{
				if (!_initialized)
				{
					((MelonBase)this).LoggerInstance.Error("Cannot scan mods - MLVScan not properly initialized");
					return new Dictionary<string, List<ScanFinding>>();
				}
				((MelonBase)this).LoggerInstance.Msg("Scanning for suspicious mods...");
				Dictionary<string, List<ScanFinding>> dictionary = (from kv in _modScanner.ScanAllMods(force)
					where kv.Value.Count > 0 && kv.Value.Any((ScanFinding f) => f.Location != "Assembly scanning")
					select kv).ToDictionary((KeyValuePair<string, List<ScanFinding>> kv) => kv.Key, (KeyValuePair<string, List<ScanFinding>> kv) => kv.Value);
				if (dictionary.Count > 0)
				{
					List<DisabledModInfo> list = _modDisabler.DisableSuspiciousMods(dictionary, force);
					int count = list.Count;
					((MelonBase)this).LoggerInstance.Msg($"Disabled {count} suspicious mods");
					if (count <= 0)
					{
						return dictionary;
					}
					GenerateDetailedReports(list, dictionary);
					((MelonBase)this).LoggerInstance.Msg("To whitelist any false positives, add their SHA256 hash to the MLVScan → WhitelistedHashes setting in MelonPreferences.cfg");
				}
				else
				{
					((MelonBase)this).LoggerInstance.Msg("No suspicious mods found");
				}
				return dictionary;
			}
			catch (Exception ex)
			{
				((MelonBase)this).LoggerInstance.Error("Error scanning mods: " + ex.Message);
				return new Dictionary<string, List<ScanFinding>>();
			}
		}

		private void GenerateDetailedReports(List<DisabledModInfo> disabledMods, Dictionary<string, List<ScanFinding>> scanResults)
		{
			bool valueOrDefault = (_configManager?.Config?.DeveloperMode).GetValueOrDefault();
			if (valueOrDefault)
			{
				((MelonBase)this).LoggerInstance.Msg("Developer Mode: Enabled");
			}
			((MelonBase)this).LoggerInstance.Warning("======= DETAILED SCAN REPORT =======");
			foreach (DisabledModInfo disabledMod in disabledMods)
			{
				string fileName = Path.GetFileName(disabledMod.OriginalPath);
				string fileHash = disabledMod.FileHash;
				string text = (File.Exists(disabledMod.DisabledPath) ? disabledMod.DisabledPath : disabledMod.OriginalPath);
				((MelonBase)this).LoggerInstance.Warning("SUSPICIOUS MOD: " + fileName);
				((MelonBase)this).LoggerInstance.Msg("SHA256 Hash: " + fileHash);
				((MelonBase)this).LoggerInstance.Msg("-------------------------------");
				if (!scanResults.TryGetValue(disabledMod.OriginalPath, out var value))
				{
					((MelonBase)this).LoggerInstance.Error("Could not find scan results for disabled mod");
					continue;
				}
				List<ScanFinding> list = value.Where((ScanFinding f) => f.Location != "Assembly scanning").ToList();
				if (list.Count == 0)
				{
					((MelonBase)this).LoggerInstance.Msg("No specific suspicious patterns were identified.");
					continue;
				}
				Dictionary<string, List<ScanFinding>> dictionary = (from f in list
					group f by f.Description).ToDictionary((IGrouping<string, ScanFinding> g) => g.Key, (IGrouping<string, ScanFinding> g) => g.ToList());
				((MelonBase)this).LoggerInstance.Warning($"Total suspicious patterns found: {list.Count}");
				Dictionary<Severity, int> dictionary2 = (from f in list
					group f by f.Severity into g
					orderby (int)g.Key descending
					select g).ToDictionary((IGrouping<Severity, ScanFinding> g) => g.Key, (IGrouping<Severity, ScanFinding> g) => g.Count());
				((MelonBase)this).LoggerInstance.Warning("Severity breakdown:");
				foreach (KeyValuePair<Severity, int> item in dictionary2)
				{
					string arg = FormatSeverityLabel(item.Key);
					((MelonBase)this).LoggerInstance.Msg($"  {arg}: {item.Value} issue(s)");
				}
				((MelonBase)this).LoggerInstance.Msg("-------------------------------");
				if (valueOrDefault && _developerReportGenerator != null)
				{
					_developerReportGenerator.GenerateConsoleReport(fileName, list);
				}
				else
				{
					((MelonBase)this).LoggerInstance.Warning("Suspicious patterns found:");
					foreach (KeyValuePair<string, List<ScanFinding>> item2 in dictionary)
					{
						item2.Deconstruct(out var key, out var value2);
						string arg2 = key;
						List<ScanFinding> list2 = value2;
						string arg3 = FormatSeverityLabel(list2[0].Severity);
						((MelonBase)this).LoggerInstance.Warning($"[{arg3}] {arg2} ({list2.Count} instances)");
						int num = Math.Min(list2.Count, 3);
						for (int i = 0; i < num; i++)
						{
							ScanFinding scanFinding = list2[i];
							((MelonBase)this).LoggerInstance.Msg("  * At: " + scanFinding.Location);
							if (!string.IsNullOrEmpty(scanFinding.CodeSnippet))
							{
								((MelonBase)this).LoggerInstance.Msg("    Code Snippet (IL):");
								string[] array = scanFinding.CodeSnippet.Split(new char[2] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries);
								foreach (string text2 in array)
								{
									((MelonBase)this).LoggerInstance.Msg("      " + text2);
								}
							}
						}
						if (list2.Count > num)
						{
							((MelonBase)this).LoggerInstance.Msg($"  * And {list2.Count - num} more instances...");
						}
						((MelonBase)this).LoggerInstance.Msg("");
					}
					((MelonBase)this).LoggerInstance.Msg("-------------------------------");
				}
				DisplaySecurityNotice(fileName);
				try
				{
					string text3 = Path.Combine(MelonEnvironment.UserDataDirectory, "MLVScan", "Reports");
					if (!Directory.Exists(text3))
					{
						Directory.CreateDirectory(text3);
					}
					string text4 = DateTime.Now.ToString("yyyyMMdd_HHmmss");
					string text5 = Path.Combine(text3, fileName + "_" + text4 + ".report.txt");
					string text6 = Path.Combine(text3, "Prompts");
					if (!Directory.Exists(text6))
					{
						Directory.CreateDirectory(text6);
					}
					ConfigManager configManager = _configManager;
					if (configManager != null && (configManager.Config?.DumpFullIlReports).GetValueOrDefault() && _ilDumpService != null)
					{
						string text7 = Path.Combine(Path.Combine(text3, "IL"), fileName + "_" + text4 + ".il.txt");
						if (_ilDumpService.TryDumpAssembly(text, text7))
						{
							((MelonBase)this).LoggerInstance.Msg("Full IL dump saved to: " + text7);
						}
						else
						{
							((MelonBase)this).LoggerInstance.Warning("Failed to dump IL for this mod (see logs for details).");
						}
					}
					PromptGeneratorService promptGeneratorService = _serviceFactory.CreatePromptGenerator();
					using (StreamWriter streamWriter = new StreamWriter(text5))
					{
						if (valueOrDefault && _developerReportGenerator != null)
						{
							string value3 = _developerReportGenerator.GenerateFileReport(fileName, fileHash, list);
							streamWriter.Write(value3);
						}
						else
						{
							streamWriter.WriteLine("MLVScan Security Report");
							streamWriter.WriteLine($"Generated: {DateTime.Now}");
							streamWriter.WriteLine("Mod File: " + fileName);
							streamWriter.WriteLine("SHA256 Hash: " + fileHash);
							streamWriter.WriteLine("Original Path: " + disabledMod.OriginalPath);
							streamWriter.WriteLine("Disabled Path: " + disabledMod.DisabledPath);
							streamWriter.WriteLine("Path Used For Analysis: " + text);
							streamWriter.WriteLine($"Total Suspicious Patterns: {list.Count}");
							streamWriter.WriteLine("\nSeverity Breakdown:");
							foreach (KeyValuePair<Severity, int> item3 in dictionary2)
							{
								streamWriter.WriteLine($"- {item3.Key}: {item3.Value} issue(s)");
							}
							streamWriter.WriteLine("==============================================");
							foreach (KeyValuePair<string, List<ScanFinding>> item4 in dictionary)
							{
								streamWriter.WriteLine("\n== " + item4.Key + " ==");
								streamWriter.WriteLine($"Severity: {item4.Value[0].Severity}");
								streamWriter.WriteLine($"Instances: {item4.Value.Count}");
								streamWriter.WriteLine("\nLocations & Snippets:");
								foreach (ScanFinding item5 in item4.Value)
								{
									streamWriter.WriteLine("- " + item5.Location);
									if (!string.IsNullOrEmpty(item5.CodeSnippet))
									{
										streamWriter.WriteLine("  Code Snippet (IL):");
										string[] array = item5.CodeSnippet.Split(new char[2] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries);
										foreach (string text8 in array)
										{
											streamWriter.WriteLine("    " + text8);
										}
										streamWriter.WriteLine();
									}
								}
							}
							WriteSecurityNoticeToReport(streamWriter);
						}
					}
					if (promptGeneratorService.SavePromptToFile(text, list, text6))
					{
						((MelonBase)this).LoggerInstance.Msg("Detailed report saved to: " + text5);
						((MelonBase)this).LoggerInstance.Msg("LLM analysis prompt saved to: " + Path.Combine(text6, fileName + ".prompt.md"));
						((MelonBase)this).LoggerInstance.Msg("You can copy the contents of the prompt file into ChatGPT to help determine if this is malware or a false positive, although don't trust ChatGPT to be 100% accurate.");
					}
					else
					{
						((MelonBase)this).LoggerInstance.Msg("Detailed report saved to: " + text5);
					}
				}
				catch (Exception ex)
				{
					((MelonBase)this).LoggerInstance.Error("Failed to save detailed report: " + ex.Message);
				}
			}
			((MelonBase)this).LoggerInstance.Warning("====== END OF SCAN REPORT ======");
		}

		private static string FormatSeverityLabel(Severity severity)
		{
			return severity switch
			{
				Severity.Critical => "CRITICAL", 
				Severity.High => "HIGH", 
				Severity.Medium => "MEDIUM", 
				Severity.Low => "LOW", 
				_ => severity.ToString().ToUpper(), 
			};
		}

		private void DisplaySecurityNotice(string modName)
		{
			((MelonBase)this).LoggerInstance.Warning("IMPORTANT SECURITY NOTICE");
			((MelonBase)this).LoggerInstance.Msg("MLVScan has detected and disabled " + modName + " before it was loaded.");
			((MelonBase)this).LoggerInstance.Msg("If this is your first time running the game with this mod, your PC is likely safe.");
			((MelonBase)this).LoggerInstance.Msg("However, if you've previously run the game with this mod, your system MAY be infected.");
			((MelonBase)this).LoggerInstance.Msg("Keep in mind that no detection system is perfect, and this mod may be falsely flagged.");
			((MelonBase)this).LoggerInstance.Warning("Recommended security steps:");
			((MelonBase)this).LoggerInstance.Msg("1. Check with the modding community first - no detection is perfect");
			((MelonBase)this).LoggerInstance.Msg("   Join the modding Discord at: https://discord.gg/UD4K4chKak");
			((MelonBase)this).LoggerInstance.Msg("   Ask about this mod in the MLVScan thread of #mod-releases to confirm if it's actually malicious");
			((MelonBase)this).LoggerInstance.Msg("2. Run a full system scan with a trusted antivirus like Malwarebytes");
			((MelonBase)this).LoggerInstance.Msg("   Malwarebytes is recommended as a free and effective antivirus solution");
			((MelonBase)this).LoggerInstance.Msg("3. Use Microsoft Safety Scanner for a secondary scan");
			((MelonBase)this).LoggerInstance.Msg("4. Change important passwords if antivirus shows a threat");
			((MelonBase)this).LoggerInstance.Warning("Resources for malware removal:");
			((MelonBase)this).LoggerInstance.Msg("- Malwarebytes: https://www.malwarebytes.com/cybersecurity/basics/how-to-remove-virus-from-computer");
			((MelonBase)this).LoggerInstance.Msg("- Microsoft Safety Scanner: https://learn.microsoft.com/en-us/defender-endpoint/safety-scanner-download");
		}

		private static void WriteSecurityNoticeToReport(StreamWriter writer)
		{
			writer.WriteLine("\n\n============== SECURITY NOTICE ==============\n");
			writer.WriteLine("IMPORTANT: READ THIS SECURITY INFORMATION\n");
			writer.WriteLine("MLVScan has detected and disabled this mod before it was loaded.");
			writer.WriteLine("This mod contains code patterns commonly associated with malware.\n");
			writer.WriteLine("YOUR SYSTEM SECURITY STATUS:");
			writer.WriteLine("- If this is your FIRST TIME starting the game with this mod installed:");
			writer.WriteLine("  Your PC is likely SAFE as MLVScan prevented the mod from loading.");
			writer.WriteLine("\n- If you have PREVIOUSLY PLAYED the game with this mod loaded:");
			writer.WriteLine("  Your system MAY BE INFECTED with malware. Take action immediately.\n");
			writer.WriteLine("RECOMMENDED SECURITY STEPS:");
			writer.WriteLine("1. Check with the modding community first - no detection system is perfect");
			writer.WriteLine("   Join the modding Discord at: https://discord.gg/UD4K4chKak");
			writer.WriteLine("   Ask about this mod in the #MLVScan or #report-mods channels to confirm if it's actually malicious");
			writer.WriteLine("\n2. Run a full system scan with a reputable antivirus program");
			writer.WriteLine("   Free option: Malwarebytes (https://www.malwarebytes.com/)");
			writer.WriteLine("   Malwarebytes is recommended as a free and effective antivirus solution");
			writer.WriteLine("\n3. Run Microsoft Safety Scanner as a secondary check");
			writer.WriteLine("   Download: https://learn.microsoft.com/en-us/defender-endpoint/safety-scanner-download");
			writer.WriteLine("\n4. Update all your software from official sources");
			writer.WriteLine("\n5. Change passwords for important accounts (from a clean device if possible)");
			writer.WriteLine("\n6. Monitor your accounts for any suspicious activity");
			writer.WriteLine("\nDETAILED MALWARE REMOVAL GUIDES:");
			writer.WriteLine("- Malwarebytes Guide: https://www.malwarebytes.com/cybersecurity/basics/how-to-remove-virus-from-computer");
			writer.WriteLine("- Microsoft Safety Scanner: https://learn.microsoft.com/en-us/defender-endpoint/safety-scanner-download");
			writer.WriteLine("\n=============================================");
		}
	}
	public class ServiceFactory
	{
		private readonly Instance _logger;

		private readonly IScanLogger _scanLogger;

		private readonly IAssemblyResolverProvider _resolverProvider;

		private readonly ConfigManager _configManager;

		private readonly ScanConfig _fallbackConfig;

		public ServiceFactory(Instance logger)
		{
			_logger = logger;
			_scanLogger = new MelonScanLogger(logger);
			_resolverProvider = new GameAssemblyResolverProvider();
			_fallbackConfig = new ScanConfig();
			try
			{
				_configManager = new ConfigManager(logger);
			}
			catch (Exception ex)
			{
				_logger.Error("Failed to create ConfigManager: " + ex.Message);
				_logger.Msg("Using default configuration values");
			}
		}

		public ConfigManager CreateConfigManager()
		{
			return _configManager;
		}

		public AssemblyScanner CreateAssemblyScanner()
		{
			ScanConfig config = _configManager?.Config ?? _fallbackConfig;
			return new AssemblyScanner(RuleFactory.CreateDefaultRules(), config, _resolverProvider);
		}

		public ModScanner CreateModScanner()
		{
			return new ModScanner(CreateAssemblyScanner(), config: _configManager?.Config ?? _fallbackConfig, logger: _logger, configManager: _configManager);
		}

		public ModDisabler CreateModDisabler()
		{
			ScanConfig config = _configManager?.Config ?? _fallbackConfig;
			return new ModDisabler(_logger, config);
		}

		public PromptGeneratorService CreatePromptGenerator()
		{
			return new PromptGeneratorService(_configManager?.Config ?? _fallbackConfig, _logger);
		}

		public IlDumpService CreateIlDumpService()
		{
			return new IlDumpService(_logger);
		}

		public DeveloperReportGenerator CreateDeveloperReportGenerator()
		{
			return new DeveloperReportGenerator(_logger);
		}
	}
}
namespace MLVScan.Services
{
	public class ConfigManager
	{
		private readonly Instance _logger;

		private readonly MelonPreferences_Category _category;

		private readonly MelonPreferences_Entry<bool> _enableAutoScan;

		private readonly MelonPreferences_Entry<bool> _enableAutoDisable;

		private readonly MelonPreferences_Entry<string> _minSeverityForDisable;

		private readonly MelonPreferences_Entry<string[]> _scanDirectories;

		private readonly MelonPreferences_Entry<int> _suspiciousThreshold;

		private readonly MelonPreferences_Entry<string[]> _whitelistedHashes;

		private readonly MelonPreferences_Entry<bool> _dumpFullIlReports;

		private readonly MelonPreferences_Entry<bool> _developerMode;

		public ScanConfig Config { get; private set; }

		public ConfigManager(Instance logger)
		{
			_logger = logger ?? throw new ArgumentNullException("logger");
			try
			{
				_category = MelonPreferences.CreateCategory("MLVScan");
				_enableAutoScan = _category.CreateEntry<bool>("EnableAutoScan", true, (string)null, "Whether to scan mods at startup", false, false, (ValueValidator)null, (string)null);
				_enableAutoDisable = _category.CreateEntry<bool>("EnableAutoDisable", true, (string)null, "Whether to disable suspicious mods", false, false, (ValueValidator)null, (string)null);
				_minSeverityForDisable = _category.CreateEntry<string>("MinSeverityForDisable", "Medium", (string)null, "Minimum severity level to trigger disabling (Low, Medium, High, Critical)", false, false, (ValueValidator)null, (string)null);
				_scanDirectories = _category.CreateEntry<string[]>("ScanDirectories", new string[2] { "Mods", "Plugins" }, (string)null, "Directories to scan for mods", false, false, (ValueValidator)null, (string)null);
				_suspiciousThreshold = _category.CreateEntry<int>("SuspiciousThreshold", 1, (string)null, "How many suspicious findings required before disabling a mod", false, false, (ValueValidator)null, (string)null);
				_whitelistedHashes = _category.CreateEntry<string[]>("WhitelistedHashes", Array.Empty<string>(), (string)null, "List of mod SHA256 hashes to skip when scanning", false, false, (ValueValidator)null, (string)null);
				_dumpFullIlReports = _category.CreateEntry<bool>("DumpFullIlReports", false, (string)null, "When enabled, saves full IL dumps for scanned mods next to reports", false, false, (ValueValidator)null, (string)null);
				_developerMode = _category.CreateEntry<bool>("DeveloperMode", false, (string)null, "Developer mode: Shows remediation guidance to help mod developers fix false positives", false, false, (ValueValidator)null, (string)null);
				((MelonEventBase<LemonAction<bool, bool>>)(object)_enableAutoScan.OnEntryValueChanged).Subscribe((LemonAction<bool, bool>)OnConfigChanged, 0, false);
				((MelonEventBase<LemonAction<bool, bool>>)(object)_enableAutoDisable.OnEntryValueChanged).Subscribe((LemonAction<bool, bool>)OnConfigChanged, 0, false);
				((MelonEventBase<LemonAction<string, string>>)(object)_minSeverityForDisable.OnEntryValueChanged).Subscribe((LemonAction<string, string>)OnConfigChanged, 0, false);
				((MelonEventBase<LemonAction<string[], string[]>>)(object)_scanDirectories.OnEntryValueChanged).Subscribe((LemonAction<string[], string[]>)OnConfigChanged, 0, false);
				((MelonEventBase<LemonAction<int, int>>)(object)_suspiciousThreshold.OnEntryValueChanged).Subscribe((LemonAction<int, int>)OnConfigChanged, 0, false);
				((MelonEventBase<LemonAction<string[], string[]>>)(object)_whitelistedHashes.OnEntryValueChanged).Subscribe((LemonAction<string[], string[]>)OnConfigChanged, 0, false);
				((MelonEventBase<LemonAction<bool, bool>>)(object)_dumpFullIlReports.OnEntryValueChanged).Subscribe((LemonAction<bool, bool>)OnConfigChanged, 0, false);
				((MelonEventBase<LemonAction<bool, bool>>)(object)_developerMode.OnEntryValueChanged).Subscribe((LemonAction<bool, bool>)OnConfigChanged, 0, false);
				UpdateConfigFromPreferences();
				_logger.Msg("Configuration loaded successfully");
			}
			catch (Exception ex)
			{
				_logger.Error("Failed to initialize config system: " + ex.Message);
				_logger.Msg("Using fallback in-memory configuration");
				Config = new ScanConfig();
			}
		}

		private void OnConfigChanged<T>(T oldValue, T newValue)
		{
			UpdateConfigFromPreferences();
			_logger.Msg("Configuration updated");
		}

		private void UpdateConfigFromPreferences()
		{
			Config = new ScanConfig
			{
				EnableAutoScan = _enableAutoScan.Value,
				EnableAutoDisable = _enableAutoDisable.Value,
				MinSeverityForDisable = ParseSeverity(_minSeverityForDisable.Value),
				ScanDirectories = _scanDirectories.Value,
				SuspiciousThreshold = _suspiciousThreshold.Value,
				WhitelistedHashes = _whitelistedHashes.Value,
				DumpFullIlReports = _dumpFullIlReports.Value,
				DeveloperMode = _developerMode.Value
			};
		}

		public void SaveConfig(ScanConfig newConfig)
		{
			try
			{
				_enableAutoScan.Value = newConfig.EnableAutoScan;
				_enableAutoDisable.Value = newConfig.EnableAutoDisable;
				_minSeverityForDisable.Value = FormatSeverity(newConfig.MinSeverityForDisable);
				_scanDirectories.Value = newConfig.ScanDirectories;
				_suspiciousThreshold.Value = newConfig.SuspiciousThreshold;
				_whitelistedHashes.Value = newConfig.WhitelistedHashes;
				_dumpFullIlReports.Value = newConfig.DumpFullIlReports;
				_developerMode.Value = newConfig.DeveloperMode;
				MelonPreferences.Save();
				_logger.Msg("Configuration saved successfully");
			}
			catch (Exception ex)
			{
				_logger.Error("Error saving configuration: " + ex.Message);
				Config = newConfig;
			}
		}

		public string[] GetWhitelistedHashes()
		{
			return _whitelistedHashes.Value;
		}

		public void SetWhitelistedHashes(string[] hashes)
		{
			if (hashes != null)
			{
				string[] array = (from h in hashes
					where !string.IsNullOrWhiteSpace(h)
					select h.ToLowerInvariant()).Distinct<string>(StringComparer.OrdinalIgnoreCase).ToArray();
				_whitelistedHashes.Value = array;
				MelonPreferences.Save();
				UpdateConfigFromPreferences();
				_logger.Msg($"Updated whitelist with {array.Length} hash(es)");
			}
		}

		public bool IsHashWhitelisted(string hash)
		{
			if (string.IsNullOrWhiteSpace(hash))
			{
				return false;
			}
			return Config.WhitelistedHashes.Contains<string>(hash.ToLowerInvariant(), StringComparer.OrdinalIgnoreCase);
		}

		private static Severity ParseSeverity(string severity)
		{
			if (string.IsNullOrWhiteSpace(severity))
			{
				return Severity.Medium;
			}
			return severity.ToLower() switch
			{
				"critical" => Severity.Critical, 
				"high" => Severity.High, 
				"medium" => Severity.Medium, 
				"low" => Severity.Low, 
				_ => Severity.Medium, 
			};
		}

		private static string FormatSeverity(Severity severity)
		{
			return severity switch
			{
				Severity.Critical => "Critical", 
				Severity.High => "High", 
				Severity.Medium => "Medium", 
				Severity.Low => "Low", 
				_ => "Medium", 
			};
		}
	}
	public class DeveloperReportGenerator
	{
		private readonly Instance _logger;

		public DeveloperReportGenerator(Instance logger)
		{
			_logger = logger ?? throw new ArgumentNullException("logger");
		}

		public void GenerateConsoleReport(string modName, List<ScanFinding> findings)
		{
			if (findings == null || findings.Count == 0)
			{
				return;
			}
			_logger.Msg("======= DEVELOPER SCAN REPORT =======");
			_logger.Msg("Mod: " + modName);
			_logger.Msg("--------------------------------------");
			_logger.Msg($"Total findings: {findings.Count}");
			_logger.Msg("");
			foreach (IGrouping<string, ScanFinding> item in from f in findings
				where f.RuleId != null
				group f by f.RuleId into g
				orderby g.Max((ScanFinding f) => f.Severity) descending
				select g)
			{
				ScanFinding scanFinding = item.First();
				int num = item.Count();
				_logger.Msg($"[{scanFinding.Severity}] {scanFinding.Description}");
				_logger.Msg("  Rule: " + scanFinding.RuleId);
				_logger.Msg($"  Occurrences: {num}");
				if (scanFinding.DeveloperGuidance != null)
				{
					_logger.Msg("");
					_logger.Msg("  Developer Guidance:");
					_logger.Msg("  " + WrapText(scanFinding.DeveloperGuidance.Remediation, 2));
					if (!string.IsNullOrEmpty(scanFinding.DeveloperGuidance.DocumentationUrl))
					{
						_logger.Msg("  Documentation: " + scanFinding.DeveloperGuidance.DocumentationUrl);
					}
					if (scanFinding.DeveloperGuidance.AlternativeApis != null && scanFinding.DeveloperGuidance.AlternativeApis.Length != 0)
					{
						_logger.Msg("  Suggested APIs: " + string.Join(", ", scanFinding.DeveloperGuidance.AlternativeApis));
					}
					if (!scanFinding.DeveloperGuidance.IsRemediable)
					{
						_logger.Warning("  ⚠ No safe alternative - this pattern should not be used in MelonLoader mods.");
					}
				}
				else
				{
					_logger.Msg("  (No developer guidance available for this rule)");
				}
				_logger.Msg("");
				_logger.Msg("  Sample locations:");
				foreach (ScanFinding item2 in item.Take(3))
				{
					_logger.Msg("    - " + item2.Location);
				}
				if (num > 3)
				{
					_logger.Msg($"    ... and {num - 3} more");
				}
				_logger.Msg("");
				_logger.Msg("--------------------------------------");
			}
			_logger.Msg("");
			_logger.Msg("For more information, visit: https://discord.gg/UD4K4chKak");
			_logger.Msg("=====================================");
		}

		public string GenerateFileReport(string modName, string hash, List<ScanFinding> findings)
		{
			StringBuilder stringBuilder = new StringBuilder();
			stringBuilder.AppendLine("======= MLVScan Developer Report =======");
			stringBuilder.AppendLine("Mod: " + modName);
			stringBuilder.AppendLine("SHA256: " + hash);
			stringBuilder.AppendLine($"Scan Date: {DateTime.Now:yyyy-MM-dd HH:mm:ss}");
			stringBuilder.AppendLine($"Total Findings: {findings.Count}");
			stringBuilder.AppendLine("");
			foreach (IGrouping<string, ScanFinding> item in from f in findings
				where f.RuleId != null
				group f by f.RuleId into g
				orderby g.Max((ScanFinding f) => f.Severity) descending
				select g)
			{
				ScanFinding scanFinding = item.First();
				int num = item.Count();
				stringBuilder.AppendLine("=========================================");
				stringBuilder.AppendLine("Rule: " + scanFinding.RuleId);
				stringBuilder.AppendLine($"Severity: {scanFinding.Severity}");
				stringBuilder.AppendLine("Description: " + scanFinding.Description);
				stringBuilder.AppendLine($"Occurrences: {num}");
				stringBuilder.AppendLine("");
				if (scanFinding.DeveloperGuidance != null)
				{
					stringBuilder.AppendLine("--- DEVELOPER GUIDANCE ---");
					stringBuilder.AppendLine("Remediation: " + scanFinding.DeveloperGuidance.Remediation);
					stringBuilder.AppendLine("");
					if (!string.IsNullOrEmpty(scanFinding.DeveloperGuidance.DocumentationUrl))
					{
						stringBuilder.AppendLine("Documentation: " + scanFinding.DeveloperGuidance.DocumentationUrl);
					}
					if (scanFinding.DeveloperGuidance.AlternativeApis != null && scanFinding.DeveloperGuidance.AlternativeApis.Length != 0)
					{
						stringBuilder.AppendLine("Suggested APIs:");
						string[] alternativeApis = scanFinding.DeveloperGuidance.AlternativeApis;
						foreach (string text in alternativeApis)
						{
							stringBuilder.AppendLine("  - " + text);
						}
					}
					if (!scanFinding.DeveloperGuidance.IsRemediable)
					{
						stringBuilder.AppendLine("");
						stringBuilder.AppendLine("WARNING: This pattern has no safe alternative and should not be used in MelonLoader mods.");
					}
					stringBuilder.AppendLine("");
				}
				else
				{
					stringBuilder.AppendLine("(No developer guidance available for this rule)");
					stringBuilder.AppendLine("");
				}
				stringBuilder.AppendLine("--- FINDINGS ---");
				foreach (ScanFinding item2 in item)
				{
					stringBuilder.AppendLine("Location: " + item2.Location);
					if (!string.IsNullOrEmpty(item2.CodeSnippet))
					{
						stringBuilder.AppendLine("Code Snippet:");
						stringBuilder.AppendLine(item2.CodeSnippet);
					}
					stringBuilder.AppendLine("");
				}
			}
			stringBuilder.AppendLine("=========================================");
			stringBuilder.AppendLine("");
			stringBuilder.AppendLine("Need help? Join the community: https://discord.gg/UD4K4chKak");
			return stringBuilder.ToString();
		}

		private string WrapText(string text, int indent)
		{
			string text2 = new string(' ', indent);
			int num = 80 - indent;
			string[] array = text.Split(' ');
			List<string> list = new List<string>();
			string text3 = "";
			string[] array2 = array;
			foreach (string text4 in array2)
			{
				if (text3.Length + text4.Length + 1 > num)
				{
					if (!string.IsNullOrEmpty(text3))
					{
						list.Add(text3);
					}
					text3 = text4;
				}
				else
				{
					text3 = text3 + ((text3.Length > 0) ? " " : "") + text4;
				}
			}
			if (!string.IsNullOrEmpty(text3))
			{
				list.Add(text3);
			}
			return string.Join("\n  " + text2, list);
		}
	}
	public class IlDumpService
	{
		private readonly Instance _logger;

		private readonly DefaultAssemblyResolver _assemblyResolver;

		public IlDumpService(Instance logger)
		{
			_logger = logger;
			_assemblyResolver = BuildResolver();
		}

		public bool TryDumpAssembly(string assemblyPath, string outputPath)
		{
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: Expected O, but got Unknown
			//IL_0091: Unknown result type (might be due to invalid IL or missing references)
			//IL_0096: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cb: Unknown result type (might be due to invalid IL or missing references)
			if (string.IsNullOrWhiteSpace(assemblyPath) || string.IsNullOrWhiteSpace(outputPath))
			{
				return false;
			}
			try
			{
				Directory.CreateDirectory(Path.GetDirectoryName(outputPath));
				ReaderParameters val = new ReaderParameters
				{
					ReadWrite = false,
					InMemory = true,
					ReadSymbols = false,
					AssemblyResolver = (IAssemblyResolver)(object)_assemblyResolver
				};
				AssemblyDefinition val2 = AssemblyDefinition.ReadAssembly(assemblyPath, val);
				using StreamWriter streamWriter = new StreamWriter(outputPath);
				streamWriter.WriteLine("; Full IL dump for " + Path.GetFileName(assemblyPath));
				streamWriter.WriteLine($"; Generated: {DateTime.Now}");
				streamWriter.WriteLine();
				Enumerator<ModuleDefinition> enumerator = val2.Modules.GetEnumerator();
				try
				{
					while (enumerator.MoveNext())
					{
						ModuleDefinition current = enumerator.Current;
						streamWriter.WriteLine(".module " + ((ModuleReference)current).Name);
						streamWriter.WriteLine();
						Enumerator<TypeDefinition> enumerator2 = current.Types.GetEnumerator();
						try
						{
							while (enumerator2.MoveNext())
							{
								WriteType(enumerator2.Current, streamWriter);
							}
						}
						finally
						{
							((IDisposable)enumerator2).Dispose();
						}
					}
				}
				finally
				{
					((IDisposable)enumerator).Dispose();
				}
				Instance logger = _logger;
				if (logger != null)
				{
					logger.Msg("Saved IL dump to: " + outputPath);
				}
				return true;
			}
			catch (Exception ex)
			{
				Instance logger2 = _logger;
				if (logger2 != null)
				{
					logger2.Error("Failed to dump IL for " + Path.GetFileName(assemblyPath) + ": " + ex.Message);
				}
				return false;
			}
		}

		private DefaultAssemblyResolver BuildResolver()
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Expected O, but got Unknown
			DefaultAssemblyResolver val = new DefaultAssemblyResolver();
			string gameRootDirectory = MelonEnvironment.GameRootDirectory;
			string text = Path.Combine(gameRootDirectory, "MelonLoader");
			((BaseAssemblyResolver)val).AddSearchDirectory(gameRootDirectory);
			if (Directory.Exists(text))
			{
				((BaseAssemblyResolver)val).AddSearchDirectory(text);
				string text2 = Path.Combine(text, "Managed");
				if (Directory.Exists(text2))
				{
					((BaseAssemblyResolver)val).AddSearchDirectory(text2);
				}
				string text3 = Path.Combine(text, "Dependencies");
				if (Directory.Exists(text3))
				{
					((BaseAssemblyResolver)val).AddSearchDirectory(text3);
					string[] directories = Directory.GetDirectories(text3, "*", SearchOption.AllDirectories);
					foreach (string text4 in directories)
					{
						((BaseAssemblyResolver)val).AddSearchDirectory(text4);
					}
				}
			}
			string text5 = Path.Combine(gameRootDirectory, "Schedule I_Data", "Managed");
			if (Directory.Exists(text5))
			{
				((BaseAssemblyResolver)val).AddSearchDirectory(text5);
			}
			return val;
		}

		private static void WriteType(TypeDefinition type, StreamWriter writer)
		{
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			writer.WriteLine(".class " + ((MemberReference)type).FullName);
			Enumerator<MethodDefinition> enumerator = type.Methods.GetEnumerator();
			try
			{
				while (enumerator.MoveNext())
				{
					WriteMethod(enumerator.Current, writer);
				}
			}
			finally
			{
				((IDisposable)enumerator).Dispose();
			}
			Enumerator<TypeDefinition> enumerator2 = type.NestedTypes.GetEnumerator();
			try
			{
				while (enumerator2.MoveNext())
				{
					WriteType(enumerator2.Current, writer);
				}
			}
			finally
			{
				((IDisposable)enumerator2).Dispose();
			}
		}

		private static void WriteMethod(MethodDefinition method, StreamWriter writer)
		{
			//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e2: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				string text = string.Join(", ", ((IEnumerable<ParameterDefinition>)((MethodReference)method).Parameters).Select((ParameterDefinition p) => ((MemberReference)((ParameterReference)p).ParameterType).FullName + " " + ((ParameterReference)p).Name));
				writer.WriteLine("  .method " + ((MemberReference)((MethodReference)method).ReturnType).FullName + " " + ((MemberReference)method).Name + "(" + text + ")");
				if (!method.HasBody)
				{
					writer.WriteLine("    // No body (abstract / external)");
					writer.WriteLine();
					return;
				}
				writer.WriteLine("  {");
				Enumerator<Instruction> enumerator = method.Body.Instructions.GetEnumerator();
				try
				{
					while (enumerator.MoveNext())
					{
						Instruction current = enumerator.Current;
						string text2 = FormatOperand(current.Operand);
						string text3 = $"    IL_{current.Offset:X4}: {current.OpCode}";
						if (!string.IsNullOrEmpty(text2))
						{
							text3 = text3 + " " + text2;
						}
						writer.WriteLine(text3);
					}
				}
				finally
				{
					((IDisposable)enumerator).Dispose();
				}
				writer.WriteLine("  }");
				writer.WriteLine();
			}
			catch (Exception ex)
			{
				writer.WriteLine("    // Failed to dump method " + ((MemberReference)method).Name + ": " + ex.Message);
				writer.WriteLine();
			}
		}

		private static string FormatOperand(object operand)
		{
			if (operand != null)
			{
				if (!(operand is string text))
				{
					MethodReference val = (MethodReference)((operand is MethodReference) ? operand : null);
					if (val == null)
					{
						FieldReference val2 = (FieldReference)((operand is FieldReference) ? operand : null);
						if (val2 == null)
						{
							TypeReference val3 = (TypeReference)((operand is TypeReference) ? operand : null);
							if (val3 == null)
							{
								Instruction val4 = (Instruction)((operand is Instruction) ? operand : null);
								if (val4 == null)
								{
									if (operand is Instruction[] source)
									{
										return string.Join(", ", source.Select((Instruction t) => $"IL_{t.Offset:X4}"));
									}
									return operand.ToString() ?? string.Empty;
								}
								return $"IL_{val4.Offset:X4}";
							}
							return ((MemberReference)val3).FullName;
						}
						return ((MemberReference)val2).FullName;
					}
					return ((MemberReference)val).FullName;
				}
				return "\"" + text + "\"";
			}
			return string.Empty;
		}
	}
	public class ModDisabler
	{
		private readonly Instance _logger = logger ?? throw new ArgumentNullException("logger");

		private readonly ScanConfig _config = config ?? throw new ArgumentNullException("config");

		private const string DisabledExtension = ".di";

		public ModDisabler(Instance logger, ScanConfig config)
		{
		}

		public List<DisabledModInfo> DisableSuspiciousMods(Dictionary<string, List<ScanFinding>> scanResults, bool forceDisable = false)
		{
			if (!forceDisable && !_config.EnableAutoDisable)
			{
				_logger.Msg("Automatic disabling is turned off in configuration");
				return new List<DisabledModInfo>();
			}
			List<DisabledModInfo> list = new List<DisabledModInfo>();
			foreach (KeyValuePair<string, List<ScanFinding>> scanResult in scanResults)
			{
				scanResult.Deconstruct(out var key, out var value);
				string text = key;
				List<ScanFinding> list2 = value.Where((ScanFinding f) => f.Severity >= _config.MinSeverityForDisable).ToList();
				if (list2.Count == 0)
				{
					_logger.Msg($"Mod {Path.GetFileName(text)} has findings but none meet minimum severity threshold ({_config.MinSeverityForDisable} - If this is set to Medium, the mod is likely not malicious).");
					continue;
				}
				if (!forceDisable && list2.Count < _config.SuspiciousThreshold)
				{
					_logger.Msg("Mod " + Path.GetFileName(text) + " has suspicious patterns but below threshold");
					continue;
				}
				try
				{
					string fileHash = ModScanner.CalculateFileHash(text);
					string text2 = Path.ChangeExtension(text, ".di");
					if (File.Exists(text2))
					{
						File.Delete(text2);
					}
					File.Move(text, text2);
					_logger.Warning("Disabled potentially malicious mod: " + Path.GetFileName(text));
					list.Add(new DisabledModInfo(text, text2, fileHash));
				}
				catch (Exception ex)
				{
					_logger.Error("Failed to disable mod " + Path.GetFileName(text) + ": " + ex.Message);
				}
			}
			return list;
		}
	}
	public class ModScanner
	{
		private readonly AssemblyScanner _assemblyScanner = assemblyScanner ?? throw new ArgumentNullException("assemblyScanner");

		private readonly Instance _logger = logger ?? throw new ArgumentNullException("logger");

		private readonly ScanConfig _config = config ?? throw new ArgumentNullException("config");

		private readonly ConfigManager _configManager = configManager ?? throw new ArgumentNullException("configManager");

		public ModScanner(AssemblyScanner assemblyScanner, Instance logger, ScanConfig config, ConfigManager configManager)
		{
		}

		public Dictionary<string, List<ScanFinding>> ScanAllMods(bool forceScanning = false)
		{
			Dictionary<string, List<ScanFinding>> dictionary = new Dictionary<string, List<ScanFinding>>();
			if (!forceScanning && !_config.EnableAutoScan)
			{
				_logger.Msg("Automatic scanning is disabled in configuration");
				return dictionary;
			}
			string[] scanDirectories = _config.ScanDirectories;
			foreach (string path in scanDirectories)
			{
				string text = Path.Combine(MelonEnvironment.GameRootDirectory, path);
				if (!Directory.Exists(text))
				{
					_logger.Warning("Directory not found: " + text);
				}
				else
				{
					ScanDirectory(text, dictionary);
				}
			}
			ScanThunderstoreModManager(dictionary);
			return dictionary;
		}

		private void ScanDirectory(string directoryPath, Dictionary<string, List<ScanFinding>> results)
		{
			string[] files = Directory.GetFiles(directoryPath, "*.dll", SearchOption.AllDirectories);
			_logger.Msg($"Found {files.Length} potential mod files in {directoryPath}");
			string[] array = files;
			foreach (string text in array)
			{
				try
				{
					string fileName = Path.GetFileName(text);
					string text2 = CalculateFileHash(text);
					if (Path.GetFullPath(text).Equals(Path.GetFullPath(typeof(Core).Assembly.Location), StringComparison.OrdinalIgnoreCase))
					{
						_logger.Msg("Skipping self: " + fileName);
					}
					else if (_configManager.IsHashWhitelisted(text2))
					{
						_logger.Msg("Skipping whitelisted mod: " + fileName + " [Hash: " + text2 + "]");
					}
					else
					{
						List<ScanFinding> list = _assemblyScanner.Scan(text).ToList();
						if (list.Count >= _config.SuspiciousThreshold)
						{
							results.Add(text, list);
							_logger.Warning($"Found {list.Count} suspicious patterns in {Path.GetFileName(text)}");
						}
					}
				}
				catch (Exception ex)
				{
					_logger.Error("Error scanning " + Path.GetFileName(text) + ": " + ex.Message);
				}
			}
		}

		private void ScanThunderstoreModManager(Dictionary<string, List<ScanFinding>> results)
		{
			try
			{
				string path = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "Thunderstore Mod Manager", "DataFolder");
				if (!Directory.Exists(path))
				{
					return;
				}
				string[] directories = Directory.GetDirectories(path);
				for (int i = 0; i < directories.Length; i++)
				{
					string path2 = Path.Combine(directories[i], "profiles");
					if (!Directory.Exists(path2))
					{
						continue;
					}
					string[] directories2 = Directory.GetDirectories(path2);
					foreach (string path3 in directories2)
					{
						string text = Path.Combine(path3, "Mods");
						if (Directory.Exists(text))
						{
							_logger.Msg("Scanning Thunderstore profile mods: " + text);
							ScanDirectory(text, results);
						}
						string text2 = Path.Combine(path3, "Plugins");
						if (Directory.Exists(text2))
						{
							_logger.Msg("Scanning Thunderstore profile plugins: " + text2);
							ScanDirectory(text2, results);
						}
					}
				}
			}
			catch (Exception ex)
			{
				_logger.Error("Error scanning Thunderstore Mod Manager directories: " + ex.Message);
			}
		}

		public static string CalculateFileHash(string filePath)
		{
			try
			{
				if (!File.Exists(filePath))
				{
					return "File not found: " + filePath;
				}
				using SHA256 sHA = SHA256.Create();
				using FileStream inputStream = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
				return BitConverter.ToString(sHA.ComputeHash(inputStream)).Replace("-", "").ToLowerInvariant();
			}
			catch (UnauthorizedAccessException)
			{
				return "Access denied";
			}
			catch (IOException ex2)
			{
				return "IO Error: " + ex2.Message;
			}
			catch (Exception ex3)
			{
				return "Error: " + ex3.Message;
			}
		}
	}
	public class PromptGeneratorService
	{
		private readonly ScanConfig _config;

		private readonly Instance _logger;

		public PromptGeneratorService(ScanConfig config, Instance logger)
		{
			_config = config ?? throw new ArgumentNullException("config");
			_logger = logger ?? throw new ArgumentNullException("logger");
		}

		public string GeneratePrompt(string modPath, List<ScanFinding> findings)
		{
			if (findings == null || !findings.Any())
			{
				return "No suspicious findings to analyze.";
			}
			string fileName = Path.GetFileName(modPath);
			StringBuilder stringBuilder = new StringBuilder();
			stringBuilder.AppendLine("# Mod Security Analysis Request");
			stringBuilder.AppendLine();
			stringBuilder.AppendLine("I need to determine if the following mod is malicious or a false positive. Below is a security scan report generated by MLVScan (a security tool for MelonLoader mods).");
			stringBuilder.AppendLine();
			stringBuilder.AppendLine("## Mod Information");
			stringBuilder.AppendLine("- **Filename**: " + fileName);
			stringBuilder.AppendLine($"- **Scan Date**: {DateTime.Now}");
			stringBuilder.AppendLine($"- **Total Suspicious Patterns**: {findings.Count}");
			stringBuilder.AppendLine();
			Dictionary<Severity, int> dictionary = (from f in findings
				group f by f.Severity into g
				orderby (int)g.Key descending
				select g).ToDictionary((IGrouping<Severity, ScanFinding> g) => g.Key, (IGrouping<Severity, ScanFinding> g) => g.Count());
			stringBuilder.AppendLine("## Severity Breakdown");
			foreach (KeyValuePair<Severity, int> item in dictionary)
			{
				stringBuilder.AppendLine($"- **{FormatSeverityLabel(item.Key)}**: {item.Value} issue(s)");
			}
			stringBuilder.AppendLine();
			stringBuilder.AppendLine("## Detailed Findings");
			Dictionary<string, List<ScanFinding>> dictionary2 = (from f in findings
				group f by f.Description).ToDictionary((IGrouping<string, ScanFinding> g) => g.Key, (IGrouping<string, ScanFinding> g) => g.ToList());
			var (dictionary5, dictionary6) = ExtractCodeBlocks(modPath, findings);
			foreach (KeyValuePair<string, List<ScanFinding>> item2 in dictionary2)
			{
				stringBuilder.AppendLine("### " + item2.Key);
				stringBuilder.AppendLine($"- **Severity**: {item2.Value[0].Severity}");
				stringBuilder.AppendLine($"- **Occurrences**: {item2.Value.Count}");
				stringBuilder.AppendLine("- **Locations & Snippets**:");
				foreach (ScanFinding item3 in item2.Value.Take(5))
				{
					stringBuilder.AppendLine("  - **Location**: " + item3.Location);
					if (!string.IsNullOrEmpty(item3.CodeSnippet))
					{
						stringBuilder.AppendLine("    **IL Snippet (Exact location of suspicious call)**:");
						stringBuilder.AppendLine("    ```");
						string[] array = item3.CodeSnippet.Split(new char[2] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries);
						foreach (string text in array)
						{
							stringBuilder.AppendLine("    " + text);
						}
						stringBuilder.AppendLine("    ```");
					}
					if (dictionary5.TryGetValue(item3.Location, out var value) && !string.IsNullOrWhiteSpace(value))
					{
						stringBuilder.AppendLine("    **Attempted C# Decompilation (Entire Method Context & Type Info)**:");
						stringBuilder.AppendLine("    ```csharp");
						string[] array = value.Split(new char[2] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries);
						foreach (string text2 in array)
						{
							stringBuilder.AppendLine("    " + text2);
						}
						stringBuilder.AppendLine("    ```");
					}
					if (dictionary6.TryGetValue(item3.Location, out var value2) && !string.IsNullOrWhiteSpace(value2))
					{
						stringBuilder.AppendLine("    **Surrounding Class Structure (Member Signatures Only)**:");
						stringBuilder.AppendLine("    ```csharp");
						string[] array = value2.Split(new char[2] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries);
						foreach (string text3 in array)
						{
							stringBuilder.AppendLine("    " + text3);
						}
						stringBuilder.AppendLine("    ```");
					}
					stringBuilder.AppendLine();
				}
				if (item2.Value.Count > 5)
				{
					stringBuilder.AppendLine($"  - *And {item2.Value.Count - 5} more occurrences (details omitted for brevity)*");
				}
				stringBuilder.AppendLine();
			}
			string value3 = ExtractAssemblyMetadata(modPath);
			if (!string.IsNullOrEmpty(value3))
			{
				stringBuilder.AppendLine("## Assembly Metadata");
				stringBuilder.AppendLine(value3);
				stringBuilder.AppendLine();
			}
			stringBuilder.AppendLine("## Request");
			stringBuilder.AppendLine("Based on this scan report and code analysis, please help me determine:");
			stringBuilder.AppendLine("1. Is this mod likely to be malicious or is it a false positive?");
			stringBuilder.AppendLine("2. If potentially malicious, what specific security risks does it pose?");
			stringBuilder.AppendLine("3. What is the intent of the suspicious code? Is there a benign explanation?");
			stringBuilder.AppendLine("4. What further actions should I take? (Whitelist it, delete it, report it, etc.)");
			stringBuilder.AppendLine();
			stringBuilder.AppendLine("Please explain your reasoning with reference to the specific code patterns and provide context about:");
			stringBuilder.AppendLine("- Whether these patterns are common in legitimate mods or game utilities");
			stringBuilder.AppendLine("- Alternative explanations for the suspicious patterns");
			stringBuilder.AppendLine("- Your confidence level in the assessment");
			stringBuilder.AppendLine();
			stringBuilder.AppendLine("Important context: This is a mod for a game using MelonLoader (a mod loading framework). Legitimate mods generally don't need to use system-level APIs like shell execution, registry access, etc.");
			return stringBuilder.ToString();
		}

		private Tuple<Dictionary<string, string>, Dictionary<string, string>> ExtractCodeBlocks(string modPath, List<ScanFinding> findings)
		{
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Expected O, but got Unknown
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_0067: Unknown result type (might be due to invalid IL or missing references)
			//IL_006c: Unknown result type (might be due to invalid IL or missing references)
			Dictionary<string, string> dictionary = new Dictionary<string, string>();
			Dictionary<string, string> dictionary2 = new Dictionary<string, string>();
			try
			{
				if (!File.Exists(modPath))
				{
					return Tuple.Create(dictionary, dictionary2);
				}
				ReaderParameters val = new ReaderParameters
				{
					ReadWrite = false,
					InMemory = true,
					ReadSymbols = false
				};
				AssemblyDefinition val2 = AssemblyDefinition.ReadAssembly(modPath, val);
				try
				{
					Dictionary<string, List<string>> dictionary3 = new Dictionary<string, List<string>>();
					Enumerator<ModuleDefinition> enumerator = val2.Modules.GetEnumerator();
					try
					{
						while (enumerator.MoveNext())
						{
							Enumerator<TypeDefinition> enumerator2 = enumerator.Current.Types.GetEnumerator();
							try
							{
								while (enumerator2.MoveNext())
								{
									TypeDefinition current = enumerator2.Current;
									CollectSuspiciousStrings(current, dictionary3);
								}
							}
							finally
							{
								((IDisposable)enumerator2).Dispose();
							}
						}
					}
					finally
					{
						((IDisposable)enumerator).Dispose();
					}
					if (dictionary3.Any())
					{
						StringBuilder stringBuilder = new StringBuilder();
						stringBuilder.AppendLine("// Notable string literals found in the assembly:");
						stringBuilder.AppendLine();
						foreach (string item in dictionary3.Keys.OrderBy((string k) => k))
						{
							stringBuilder.AppendLine("// Potential " + item + ":");
							foreach (string item2 in dictionary3[item].Take(10))
							{
								stringBuilder.AppendLine("//   \"" + EscapeStringForCode(item2) + "\"");
							}
							if (dictionary3[item].Count > 10)
							{
								stringBuilder.AppendLine($"//   ... and {dictionary3[item].Count - 10} more");
							}
							stringBuilder.AppendLine();
						}
						dictionary["SuspiciousStrings"] = stringBuilder.ToString();
					}
					foreach (ScanFinding finding in findings)
					{
						try
						{
							string location = finding.Location;
							if (location == "Assembly scanning" || !location.Contains("."))
							{
								continue;
							}
							_ = string.Empty;
							string fullTypeName;
							string methodNameFromFinding;
							if (location.Contains(":"))
							{
								string[] array = location.Split(':');
								string text = array[0];
								_ = array[1];
								int num = text.LastIndexOf('.');
								if (num > 0)
								{
									fullTypeName = text.Substring(0, num);
									methodNameFromFinding = text.Substring(num + 1);
									goto IL_02d1;
								}
							}
							else
							{
								int num2 = location.LastIndexOf('.');
								if (num2 > 0)
								{
									fullTypeName = location.Substring(0, num2);
									methodNameFromFinding = location.Substring(num2 + 1);
									goto IL_02d1;
								}
							}
							goto end_IL_0212;
							IL_02d1:
							TypeDefinition val3 = FindType(val2.MainModule, fullTypeName);
							if (val3 == null)
							{
								continue;
							}
							if (!dictionary2.ContainsKey(finding.Location) || dictionary2[finding.Location] == string.Empty)
							{
								dictionary2[finding.Location] = GenerateClassStructure(val3, methodNameFromFinding);
							}
							MethodDefinition val4 = ((IEnumerable<MethodDefinition>)val3.Methods).FirstOrDefault((Func<MethodDefinition, bool>)((MethodDefinition m) => ((MemberReference)m).Name == methodNameFromFinding));
							if (val4 == null)
							{
								if (!dictionary.ContainsKey(finding.Location))
								{
									dictionary[finding.Location] = "// DllImport or external method: " + finding.Location + ". Primary context is the IL snippet and class structure.";
								}
								continue;
							}
							if (!val4.HasBody && !val4.IsAbstract)
							{
								if (!dictionary.ContainsKey(finding.Location))
								{
									dictionary[finding.Location] = "// Method " + methodNameFromFinding + " has no body or is abstract.";
								}
								continue;
							}
							string text2 = DecompileMethod(val4);
							if (string.IsNullOrEmpty(text2))
							{
								continue;
							}
							StringBuilder stringBuilder2 = new StringBuilder();
							stringBuilder2.AppendLine("// Context: Method is part of " + ((MemberReference)val3).FullName);
							if (val3.HasCustomAttributes)
							{
								stringBuilder2.AppendLine("// Type attributes:");
								foreach (CustomAttribute item3 in ((IEnumerable<CustomAttribute>)val3.CustomAttributes).Take(5))
								{
									stringBuilder2.AppendLine("// - " + ((MemberReference)item3.AttributeType).Name);
								}
								if (val3.CustomAttributes.Count > 5)
								{
									stringBuilder2.AppendLine($"// - ...and {val3.CustomAttributes.Count - 5} more");
								}
							}
							if (val3.BaseType != null && ((MemberReference)val3.BaseType).FullName != "System.Object")
							{
								stringBuilder2.AppendLine("// Inherits from: " + ((MemberReference)val3.BaseType).FullName);
							}
							List<MethodDefinition> list = FindRelatedSuspiciousMethods(val3, val4);
							if (list.Any())
							{
								stringBuilder2.AppendLine("// Other suspicious methods in this class (names only):");
								foreach (MethodDefinition item4 in list.Take(3))
								{
									stringBuilder2.AppendLine("// - " + ((MemberReference)item4).Name);
								}
								if (list.Count > 3)
								{
									stringBuilder2.AppendLine($"// - ...and {list.Count - 3} more");
								}
							}
							stringBuilder2.AppendLine();
							stringBuilder2.AppendLine("// Finding Description: " + finding.Description);
							stringBuilder2.AppendLine($"// Severity: {finding.Severity}");
							stringBuilder2.AppendLine();
							dictionary[finding.Location] = stringBuilder2.ToString() + text2;
							end_IL_0212:;
						}
						catch (Exception ex)
						{
							_logger.Error("Failed to extract code for " + finding.Location + ": " + ex.Message);
							dictionary[finding.Location] = "// Error extracting detailed code for " + finding.Location + ": " + ex.Message;
						}
					}
					if (((IEnumerable<Resource>)val2.MainModule.Resources).Any())
					{
						StringBuilder stringBuilder3 = new StringBuilder();
						stringBuilder3.AppendLine("// Assembly Resources (could contain hidden payloads):");
						foreach (Resource item5 in ((IEnumerable<Resource>)val2.MainModule.Resources).Take(20))
						{
							stringBuilder3.AppendLine("//   " + item5.Name + " - " + GetResourceTypeName(item5));
						}
						if (val2.MainModule.Resources.Count > 20)
						{
							stringBuilder3.AppendLine($"//   ...and {val2.MainModule.Resources.Count - 20} more resources");
						}
						dictionary["Assembly.Resources"] = stringBuilder3.ToString();
					}
				}
				finally
				{
					((IDisposable)val2)?.Dispose();
				}
			}
			catch (Exception ex2)
			{
				_logger.Error("Failed to extract code blocks from " + modPath + ": " + ex2.Message);
			}
			return Tuple.Create(dictionary, dictionary2);
		}

		private void CollectSuspiciousStrings(TypeDefinition type, Dictionary<string, List<string>> suspiciousStrings)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ee: Unknown result type (might be due to invalid IL or missing references)
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			Enumerator<MethodDefinition> enumerator = type.Methods.GetEnumerator();
			try
			{
				while (enumerator.MoveNext())
				{
					MethodDefinition current = enumerator.Current;
					if (!current.HasBody)
					{
						continue;
					}
					Enumerator<Instruction> enumerator2 = current.Body.Instructions.GetEnumerator();
					try
					{
						while (enumerator2.MoveNext())
						{
							Instruction current2 = enumerator2.Current;
							OpCode opCode = current2.OpCode;
							if (((OpCode)(ref opCode)).Name == "ldstr" && current2.Operand is string text && IsSuspiciousString(text, out var category))
							{
								if (!suspiciousStrings.ContainsKey(category))
								{
									suspiciousStrings[category] = new List<string>();
								}
								if (!suspiciousStrings[category].Contains(text))
								{
									suspiciousStrings[category].Add(text);
								}
							}
						}
					}
					finally
					{
						((IDisposable)enumerator2).Dispose();
					}
				}
			}
			finally
			{
				((IDisposable)enumerator).Dispose();
			}
			Enumerator<TypeDefinition> enumerator3 = type.NestedTypes.GetEnumerator();
			try
			{
				while (enumerator3.MoveNext())
				{
					TypeDefinition current3 = enumerator3.Current;
					CollectSuspiciousStrings(current3, suspiciousStrings);
				}
			}
			finally
			{
				((IDisposable)enumerator3).Dispose();
			}
		}

		private bool IsSuspiciousString(string value, out string category)
		{
			if (string.IsNullOrEmpty(value))
			{
				category = string.Empty;
				return false;
			}
			if (value.Length > 20 && IsLikelyBase64(value))
			{
				category = "Base64 encoded data";
				return true;
			}
			if (value.StartsWith("http://") || value.StartsWith("https://") || value.StartsWith("ftp://") || value.StartsWith("ws://"))
			{
				category = "URL";
				return true;
			}
			if (value.Contains(".exe") || value.Contains(".dll") || value.Contains(".bat") || value.Contains(".cmd") || value.Contains(".ps1") || value.Contains(".vbs"))
			{
				category = "executable file reference";
				return true;
			}
			if (IsLikelyIPAddress(value))
			{
				category = "IP address";
				return true;
			}
			if (value.StartsWith("HKEY_") || value.Contains("\\Software\\") || value.Contains("\\Microsoft\\") || value.Contains("\\System\\"))
			{
				category = "registry path";
				return true;
			}
			if (value.StartsWith("cmd ") || value.StartsWith("powershell ") || value.Contains(" /c ") || value.Contains(" /k "))
			{
				category = "command line";
				return true;
			}
			if (value.Contains("encrypt") || value.Contains("decrypt") || value.Contains("aes") || value.Contains("rsa") || value.Contains("md5") || value.Contains("sha") || value.Contains("hash"))
			{
				category = "cryptographic reference";
				return true;
			}
			if ((value.Contains(".") && !value.Contains(" ") && !value.Contains("\\") && !value.EndsWith(".cs") && !value.EndsWith(".txt") && value.Length > 5) || value.Contains("pastebin") || value.Contains("discord") || value.Contains("webhook"))
			{
				category = "domain or web service";
				return true;
			}
			category = string.Empty;
			return false;
		}

		private bool IsLikelyBase64(string value)
		{
			if (value.Length % 4 != 0)
			{
				return false;
			}
			foreach (char c2 in value)
			{
				if ((c2 < 'A' || c2 > 'Z') && (c2 < 'a' || c2 > 'z') && (c2 < '0' || c2 > '9') && c2 != '+' && c2 != '/' && c2 != '=')
				{
					return false;
				}
			}
			if (value.Length > 20 && value.Any((char c) => c >= 'A' && c <= 'Z') && value.Any((char c) => c >= 'a' && c <= 'z'))
			{
				return value.Any((char c) => c >= '0' && c <= '9');
			}
			return false;
		}

		private bool IsLikelyIPAddress(string value)
		{
			string pattern = "^\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}";
			string pattern2 = "^[0-9a-fA-F:]+";
			if (!Regex.IsMatch(value, pattern))
			{
				return Regex.IsMatch(value, pattern2);
			}
			return true;
		}

		private string GetResourceTypeName(Resource resource)
		{
			//IL_0167: Unknown result type (might be due to invalid IL or missing references)
			//IL_016c: Unknown result type (might be due to invalid IL or missing references)
			EmbeddedResource val = (EmbeddedResource)(object)((resource is EmbeddedResource) ? resource : null);
			if (val != null)
			{
				using (Stream stream = val.GetResourceStream())
				{
					if (stream.Length > 0)
					{
						byte[] array = new byte[Math.Min(stream.Length, 16L)];
						stream.Read(array, 0, array.Length);
						if (array.Length >= 2 && array[0] == 77 && array[1] == 90)
						{
							return "PE File/DLL (MZ header)";
						}
						if (array.Length >= 4 && array[0] == 127 && array[1] == 69 && array[2] == 76 && array[3] == 70)
						{
							return "ELF Binary";
						}
						if (array.Length >= 4 && array[0] == 80 && array[1] == 75 && array[2] == 3 && array[3] == 4)
						{
							return "ZIP Archive";
						}
						if (array.Length >= 2 && array[0] == byte.MaxValue && array[1] == 216)
						{
							return "JPEG Image";
						}
						if (array.Length >= 3 && array[0] == 71 && array[1] == 73 && array[2] == 70)
						{
							return "GIF Image";
						}
						if (array.Length >= 4 && ((array[0] == 137 && array[1] == 80 && array[2] == 78 && array[3] == 71) || (array[0] == 66 && array[1] == 77)))
						{
							return "PNG or BMP Image";
						}
						return $"Binary data ({stream.Length} bytes)";
					}
					return "Empty resource";
				}
			}
			ResourceType resourceType = resource.ResourceType;
			return ((object)(ResourceType)(ref resourceType)).ToString();
		}

		private List<MethodDefinition> FindRelatedSuspiciousMethods(TypeDefinition type, MethodDefinition currentMethod)
		{
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_006e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0073: Unknown result type (might be due to invalid IL or missing references)
			//IL_008a: Unknown result type (might be due to invalid IL or missing references)
			//IL_008f: Unknown result type (might be due to invalid IL or missing references)
			List<MethodDefinition> list = new List<MethodDefinition>();
			Enumerator<MethodDefinition> enumerator = type.Methods.GetEnumerator();
			try
			{
				while (enumerator.MoveNext())
				{
					MethodDefinition current = enumerator.Current;
					if (current == currentMethod || !current.HasBody)
					{
						continue;
					}
					Enumerator<Instruction> enumerator2 = current.Body.Instructions.GetEnumerator();
					try
					{
						while (enumerator2.MoveNext())
						{
							Instruction current2 = enumerator2.Current;
							OpCode opCode = current2.OpCode;
							if (!(((OpCode)(ref opCode)).Name == "call"))
							{
								opCode = current2.OpCode;
								if (!(((OpCode)(ref opCode)).Name == "callvirt"))
								{
									opCode = current2.OpCode;
									if (!(((OpCode)(ref opCode)).Name == "newobj"))
									{
										continue;
									}
								}
							}
							object operand = current2.Operand;
							MethodReference val = (MethodReference)((operand is MethodReference) ? operand : null);
							if (val != null && IsSuspiciousMethodCall(val))
							{
								list.Add(current);
								break;
							}
						}
					}
					finally
					{
						((IDisposable)enumerator2).Dispose();
					}
				}
				return list;
			}
			finally
			{
				((IDisposable)enumerator).Dispose();
			}
		}

		private TypeDefinition FindType(ModuleDefinition module, string fullTypeName)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			Enumerator<TypeDefinition> enumerator = module.Types.GetEnumerator();
			try
			{
				while (enumerator.MoveNext())
				{
					TypeDefinition current = enumerator.Current;
					if (((MemberReference)current).FullName == fullTypeName)
					{
						return current;
					}
					TypeDefinition val = FindNestedType(current, fullTypeName);
					if (val != null)
					{
						return val;
					}
				}
			}
			finally
			{
				((IDisposable)enumerator).Dispose();
			}
			return null;
		}

		private TypeDefinition FindNestedType(TypeDefinition parentType, string fullTypeName)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			Enumerator<TypeDefinition> enumerator = parentType.NestedTypes.GetEnumerator();
			try
			{
				while (enumerator.MoveNext())
				{
					TypeDefinition current = enumerator.Current;
					if (((MemberReference)current).FullName == fullTypeName)
					{
						return current;
					}
					TypeDefinition val = FindNestedType(current, fullTypeName);
					if (val != null)
					{
						return val;
					}
				}
			}
			finally
			{
				((IDisposable)enumerator).Dispose();
			}
			return null;
		}

		private string DecompileMethod(MethodDefinition method)
		{
			//IL_032e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0333: Unknown result type (might be due to invalid IL or missing references)
			//IL_03b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_03b8: Unknown result type (might be due to invalid IL or missing references)
			if (!method.HasBody)
			{
				return string.Empty;
			}
			StringBuilder stringBuilder = new StringBuilder();
			stringBuilder.AppendLine(GetMethodVisibility(method) + " " + ((MemberReference)((MethodReference)method).ReturnType).Name + " " + ((MemberReference)method).Name + "(" + GetMethodParameters(method) + ")");
			stringBuilder.AppendLine("{");
			string value = ReconstructCode(method);
			if (!string.IsNullOrEmpty(value))
			{
				stringBuilder.AppendLine(value);
			}
			else
			{
				stringBuilder.AppendLine("    // Method body:");
				List<ExceptionHandler> source = ((IEnumerable<ExceptionHandler>)method.Body.ExceptionHandlers).ToList();
				HashSet<int> hashSet = source.Select((ExceptionHandler h) => h.HandlerStart.Offset).ToHashSet();
				HashSet<int> hashSet2 = source.Select(delegate(ExceptionHandler h)
				{
					Instruction handlerEnd = h.HandlerEnd;
					return (handlerEnd == null) ? int.MaxValue : handlerEnd.Offset;
				}).ToHashSet();
				HashSet<int> hashSet3 = source.Select((ExceptionHandler h) => h.TryStart.Offset).ToHashSet();
				HashSet<int> hashSet4 = source.Select(delegate(ExceptionHandler h)
				{
					Instruction tryEnd = h.TryEnd;
					return (tryEnd == null) ? int.MaxValue : tryEnd.Offset;
				}).ToHashSet();
				bool flag = false;
				bool flag2 = false;
				List<VariableDefinition> variables = ((IEnumerable<VariableDefinition>)method.Body.Variables).ToList();
				List<ParameterDefinition> parameters = ((IEnumerable<ParameterDefinition>)((MethodReference)method).Parameters).ToList();
				List<Instruction> list = ((IEnumerable<Instruction>)method.Body.Instructions).ToList();
				for (int i = 0; i < list.Count; i++)
				{
					Instruction instruction = list[i];
					if (hashSet3.Contains(instruction.Offset) && !flag)
					{
						stringBuilder.AppendLine("    try {");
						flag = true;
					}
					if (hashSet.Contains(instruction.Offset) && !flag2)
					{
						ExceptionHandler val = ((IEnumerable<ExceptionHandler>)source).FirstOrDefault((Func<ExceptionHandler, bool>)((ExceptionHandler h) => h.HandlerStart.Offset == instruction.Offset));
						object obj;
						if (val == null)
						{
							obj = null;
						}
						else
						{
							TypeReference catchType = val.CatchType;
							obj = ((catchType != null) ? ((MemberReference)catchType).Name : null);
						}
						if (obj == null)
						{
							obj = "Exception";
						}
						stringBuilder.AppendLine("    } catch (" + (string?)obj + ") {");
						flag = false;
						flag2 = true;
					}
					if ((hashSet4.Contains(instruction.Offset) && flag) || (hashSet2.Contains(instruction.Offset) && flag2))
					{
						stringBuilder.AppendLine("    }");
						flag = false;
						flag2 = false;
					}
					string text = FormatInstructionWithContext(instruction, i, list, variables, parameters);
					if (!string.IsNullOrEmpty(text))
					{
						string text2 = "    ";
						if (flag || flag2)
						{
							text2 += "    ";
						}
						stringBuilder.AppendLine(text2 + text);
					}
				}
				if (flag || flag2)
				{
					stringBuilder.AppendLine("    }");
				}
			}
			if (((MethodReference)method).Parameters.Count > 0)
			{
				stringBuilder.AppendLine();
				stringBuilder.AppendLine("    // Method parameters:");
				Enumerator<ParameterDefinition> enumerator = ((MethodReference)method).Parameters.GetEnumerator();
				try
				{
					while (enumerator.MoveNext())
					{
						ParameterDefinition current = enumerator.Current;
						stringBuilder.AppendLine("    // " + ((MemberReference)((ParameterReference)current).ParameterType).FullName + " " + ((ParameterReference)current).Name);
					}
				}
				finally
				{
					((IDisposable)enumerator).Dispose();
				}
			}
			if (method.Body.Variables.Count > 0)
			{
				stringBuilder.AppendLine();
				stringBuilder.AppendLine("    // Local variables:");
				Enumerator<VariableDefinition> enumerator2 = method.Body.Variables.GetEnumerator();
				try
				{
					while (enumerator2.MoveNext())
					{
						VariableDefinition current2 = enumerator2.Current;
						stringBuilder.AppendLine($"    // {((MemberReference)((VariableReference)current2).VariableType).FullName} var_{((VariableReference)current2).Index}");
					}
				}
				finally
				{
					((IDisposable)enumerator2).Dispose();
				}
			}
			List<string> list2 = FindSuspiciousApiCalls(method);
			if (list2.Any())
			{
				stringBuilder.AppendLine();
				stringBuilder.AppendLine("    // Suspicious API calls:");
				foreach (string item in list2)
				{
					stringBuilder.AppendLine("    // " + item);
				}
			}
			stringBuilder.AppendLine("}");
			return stringBuilder.ToString();
		}

		private string ReconstructCode(MethodDefinition method)
		{
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fb: Unknown result type (might be due to invalid IL or missing references)
			StringBuilder stringBuilder = new StringBuilder();
			try
			{
				List<Instruction> list = ((IEnumerable<Instruction>)method.Body.Instructions).ToList();
				for (int i = 0; i < list.Count; i++)
				{
					Instruction val = list[i];
					OpCode opCode = val.OpCode;
					if (!(((OpCode)(ref opCode)).Name == "call"))
					{
						opCode = val.OpCode;
						if (!(((OpCode)(ref opCode)).Name == "callvirt"))
						{
							opCode = val.OpCode;
							if (((OpCode)(ref opCode)).Name == "newobj")
							{
								object operand = val.Operand;
								MethodReference val2 = (MethodReference)((operand is MethodReference) ? operand : null);
								if (val2 != null)
								{
									stringBuilder.AppendLine("    new " + ((MemberReference)((MemberReference)val2).DeclaringType).Name + "(...);");
									continue;
								}
							}
							opCode = val.OpCode;
							if (((OpCode)(ref opCode)).Name == "ldstr" && val.Operand is string value)
							{
								stringBuilder.AppendLine("    // String: \"" + EscapeStringForCode(value) + "\"");
							}
							continue;
						}
					}
					object operand2 = val.Operand;
					MethodReference val3 = (MethodReference)((operand2 is MethodReference) ? operand2 : null);
					if (val3 != null)
					{
						string methodCallRepresentation = GetMethodCallRepresentation(val3, list, i);
						if (!string.IsNullOrEmpty(methodCallRepresentation))
						{
							stringBuilder.AppendLine("    " + methodCallRepresentation + ";");
						}
					}
				}
				if (stringBuilder.Length == 0)
				{
					return string.Empty;
				}
				return stringBuilder.ToString();
			}
			catch
			{
				return string.Empty;
			}
		}

		private string EscapeStringForCode(string value)
		{
			if (string.IsNullOrEmpty(value))
			{
				return value;
			}
			return value.Replace("\"", "\\\"").Replace("\r", "\\r").Replace("\n", "\\n")
				.Replace("\t", "\\t");
		}

		private string GetMethodCallRepresentation(MethodReference methodRef, List<Instruction> instructions, int currentIndex)
		{
			//IL_009e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
			string name = ((MemberReference)methodRef).Name;
			string name2 = ((MemberReference)((MemberReference)methodRef).DeclaringType).Name;
			if (name.Contains("Process") && name.Contains("Start"))
			{
				return "System.Diagnostics.Process.Start(...) // Executes external process";
			}
			if (name.Contains("Load") && name2.Contains("Assembly"))
			{
				return "Assembly." + name + "(...) // Dynamically loads code";
			}
			if ((name.Contains("FromBase64") || name.Contains("GetString")) && name2.Contains("Convert"))
			{
				string text = "...";
				for (int num = currentIndex - 1; num >= Math.Max(0, currentIndex - 5); num--)
				{
					OpCode opCode = instructions[num].OpCode;
					if (((OpCode)(ref opCode)).Name == "ldstr" && instructions[num].Operand is string)
					{
						text = instructions[num].Operand.ToString();
						if (text.Length > 20)
						{
							text = text.Substring(0, 17) + "...";
						}
						break;
					}
				}
				return "Convert." + name + "(\"" + text + "\") // Decodes Base64 data";
			}
			if (name.Contains("RegOpenKey") || name.Contains("RegCreateKey") || (name.Contains("Registry") && (name.Contains("Get") || name.Contains("Set"))))
			{
				return name2 + "." + name + "(...) // Registry manipulation";
			}
			if (name.Contains("CreateFile") || name.Contains("WriteFile") || name.Contains("ReadFile"))
			{
				return name2 + "." + name + "(...) // File system operation";
			}
			if (name.Contains("Socket") || name.Contains("Connect") || name.Contains("Send") || name.Contains("Receive"))
			{
				return name2 + "." + name + "(...) // Network communication";
			}
			return name2 + "." + name + "(...)";
		}

		private string FormatInstructionWithContext(Instruction instruction, int index, List<Instruction> allInstructions, List<VariableDefinition> variables, List<ParameterDefinition> parameters)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			OpCode opCode = instruction.OpCode;
			string name = ((OpCode)(ref opCode)).Name;
			if (name == "nop")
			{
				return string.Empty;
			}
			StringBuilder stringBuilder = new StringBuilder();
			stringBuilder.Append($"/* {instruction.Offset:X4} */ ");
			object operand = instruction.Operand;
			MethodReference val = (MethodReference)((operand is MethodReference) ? operand : null);
			if (val != null)
			{
				stringBuilder.Append(name + " " + ((MemberReference)((MemberReference)val).DeclaringType).FullName + "." + ((MemberReference)val).Name + "()");
				if (val.Parameters.Count > 0)
				{
					stringBuilder.Append(" // Takes: " + string.Join(", ", ((IEnumerable<ParameterDefinition>)val.Parameters).Select((ParameterDefinition p) => ((MemberReference)((ParameterReference)p).ParameterType).Name)));
				}
				if (IsSuspiciousMethodCall(val))
				{
					stringBuilder.Append(" // SUSPICIOUS: " + GetSuspiciousMethodDescription(val));
				}
			}
			else
			{
				object operand2 = instruction.Operand;
				TypeReference val2 = (TypeReference)((operand2 is TypeReference) ? operand2 : null);
				if (val2 != null)
				{
					stringBuilder.Append(name + " " + ((MemberReference)val2).FullName);
				}
				else
				{
					object operand3 = instruction.Operand;
					FieldReference val3 = (FieldReference)((operand3 is FieldReference) ? operand3 : null);
					if (val3 != null)
					{
						stringBuilder.Append(name + " " + ((MemberReference)((MemberReference)val3).DeclaringType).Name + "." + ((MemberReference)val3).Name);
					}
					else
					{
						object operand4 = instruction.Operand;
						VariableDefinition val4 = (VariableDefinition)((operand4 is VariableDefinition) ? operand4 : null);
						if (val4 != null)
						{
							string name2 = ((MemberReference)((VariableReference)val4).VariableType).Name;
							stringBuilder.Append($"{name} V_{((VariableReference)val4).Index} /* {name2} */");
						}
						else
						{
							object operand5 = instruction.Operand;
							ParameterDefinition val5 = (ParameterDefinition)((operand5 is ParameterDefinition) ? operand5 : null);
							if (val5 != null)
							{
								string name3 = ((MemberReference)((ParameterReference)val5).ParameterType).Name;
								stringBuilder.Append(name + " " + ((ParameterReference)val5).Name + " /* " + name3 + " */");
							}
							else if (instruction.Operand is string text)
							{
								string text2 = text;
								if (text2.Length > 50)
								{
									text2 = text2.Substring(0, 47) + "...";
								}
								stringBuilder.Append(name + " \"" + EscapeStringForCode(text2) + "\"");
							}
							else
							{
								object operand6 = instruction.Operand;
								Instruction val6 = (Instruction)((operand6 is Instruction) ? operand6 : null);
								if (val6 != null)
								{
									stringBuilder.Append($"{name} IL_{val6.Offset:X4}");
								}
								else
								{
									string text3 = instruction.Operand?.ToString() ?? string.Empty;
									stringBuilder.Append(name + " " + text3);
								}
							}
						}
					}
				}
			}
			return stringBuilder.ToString();
		}

		private bool IsSuspiciousMethodCall(MethodReference methodRef)
		{
			string fullName = ((MemberReference)((MemberReference)methodRef).DeclaringType).FullName;
			string name = ((MemberReference)methodRef).Name;
			if ((!fullName.Contains("Process") || !name.Contains("Start")) && (!fullName.Contains("Assembly") || (!name.Contains("Load") && !name.Contains("LoadFrom") && !name.Contains("LoadFile"))) && (!fullName.Contains("Convert") || !name.Contains("FromBase64")) && ((!fullName.Contains("Registry") && !name.Contains("Reg")) || (!name.Contains("CreateKey") && !name.Contains("OpenKey") && !name.Contains("SetValue") && !name.Contains("GetValue"))) && !fullName.Contains("Shell32") && !name.Contains("ShellExecute"))
			{
				if (fullName.Contains("Socket") || fullName.Contains("Http") || fullName.Contains("Tcp") || fullName.Contains("Web") || fullName.Contains("Net"))
				{
					if (!name.Contains("Connect") && !name.Contains("Send") && !name.Contains("Download"))
					{
						return name.Contains("Upload");
					}
					return true;
				}
				return false;
			}
			return true;
		}

		private string GetSuspiciousMethodDescription(MethodReference methodRef)
		{
			string fullName = ((MemberReference)((MemberReference)methodRef).DeclaringType).FullName;
			string name = ((MemberReference)methodRef).Name;
			if (fullName.Contains("Process") && name.Contains("Start"))
			{
				return "Executes external programs";
			}
			if (fullName.Contains("Assembly") && (name.Contains("Load") || name.Contains("LoadFrom") || name.Contains("LoadFile")))
			{
				return "Dynamically loads code which could be malicious";
			}
			if (fullName.Contains("Convert") && name.Contains("FromBase64"))
			{
				return "Decodes potentially obfuscated data";
			}
			if ((fullName.Contains("Registry") || name.Contains("Reg")) && (name.Contains("CreateKey") || name.Contains("OpenKey") || name.Contains("SetValue") || name.Contains("GetValue")))
			{
				return "Manipulates system registry which can persist malware";
			}
			if (fullName.Contains("Shell32") || name.Contains("ShellExecute"))
			{
				return "Executes system commands";
			}
			if ((fullName.Contains("Socket") || fullName.Contains("Http") || fullName.Contains("Tcp") || fullName.Contains("Web") || fullName.Contains("Net")) && (name.Contains("Connect") || name.Contains("Send") || name.Contains("Download") || name.Contains("Upload")))
			{
				return "Performs network operations that could exfiltrate data or download malware";
			}
			return "Potentially suspicious behavior";
		}

		private List<string> FindSuspiciousApiCalls(MethodDefinition method)
		{
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_005b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0060: Unknown result type (might be due to invalid IL or missing references)
			List<string> list = new List<string>();
			Enumerator<Instruction> enumerator = method.Body.Instructions.GetEnumerator();
			try
			{
				while (enumerator.MoveNext())
				{
					Instruction current = enumerator.Current;
					OpCode opCode = current.OpCode;
					if (!(((OpCode)(ref opCode)).Name == "call"))
					{
						opCode = current.OpCode;
						if (!(((OpCode)(ref opCode)).Name == "callvirt"))
						{
							opCode = current.OpCode;
							if (!(((OpCode)(ref opCode)).Name == "newobj"))
							{
								continue;
							}
						}
					}
					object operand = current.Operand;
					MethodReference val = (MethodReference)((operand is MethodReference) ? operand : null);
					if (val != null && IsSuspiciousMethodCall(val))
					{
						list.Add(((MemberReference)((MemberReference)val).DeclaringType).FullName + "." + ((MemberReference)val).Name + "() - " + GetSuspiciousMethodDescription(val));
					}
				}
			}
			finally
			{
				((IDisposable)enumerator).Dispose();
			}
			return list.Distinct().ToList();
		}

		private string GetFieldVisibility(FieldDefinition field)
		{
			if (field.IsPublic)
			{
				return "public";
			}
			if (field.IsPrivate)
			{
				return "private";
			}
			if (field.IsFamily)
			{
				return "protected";
			}
			if (field.IsFamilyOrAssembly)
			{
				return "protected internal";
			}
			if (field.IsAssembly)
			{
				return "internal";
			}
			return "private";
		}

		private string GetPropertyVisibility(PropertyDefinition prop)
		{
			MethodDefinition getMethod = prop.GetMethod;
			MethodDefinition setMethod = prop.SetMethod;
			if ((getMethod != null && getMethod.IsPublic) || (setMethod != null && setMethod.IsPublic))
			{
				return "public";
			}
			if ((getMethod != null && getMethod.IsFamilyOrAssembly) || (setMethod != null && setMethod.IsFamilyOrAssembly))
			{
				return "protected internal";
			}
			if ((getMethod != null && getMethod.IsFamily) || (setMethod != null && setMethod.IsFamily))
			{
				return "protected";
			}
			if ((getMethod != null && getMethod.IsAssembly) || (setMethod != null && setMethod.IsAssembly))
			{
				return "internal";
			}
			if ((getMethod != null && getMethod.IsPrivate) || (setMethod != null && setMethod.IsPrivate))
			{
				return "private";
			}
			if (getMethod == null)
			{
				return "public";
			}
			return "public";
		}

		private string GenerateClassStructure(TypeDefinition typeDef, string highlightMethodName = null)
		{
			//IL_006f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0074: Unknown result type (might be due to invalid IL or missing references)
			if (typeDef == null)
			{
				return string.Empty;
			}
			StringBuilder stringBuilder = new StringBuilder();
			stringBuilder.AppendLine("// Class Outline: " + ((MemberReference)typeDef).FullName);
			if (typeDef.BaseType != null && ((MemberReference)typeDef.BaseType).FullName != "System.Object")
			{
				stringBuilder.AppendLine("// Inherits from: " + ((MemberReference)typeDef.BaseType).FullName);
			}
			if (typeDef.HasInterfaces)
			{
				Enumerator<InterfaceImplementation> enumerator = typeDef.Interfaces.GetEnumerator();
				try
				{
					while (enumerator.MoveNext())
					{
						InterfaceImplementation current = enumerator.Current;
						stringBuilder.AppendLine("// Implements: " + ((MemberReference)current.InterfaceType).FullName);
					}
				}
				finally
				{
					((IDisposable)enumerator).Dispose();
				}
			}
			string text = "class";
			if (typeDef.IsInterface)
			{
				text = "interface";
			}
			else if (typeDef.IsEnum)
			{
				text = "enum";
			}
			else if (((TypeReference)typeDef).IsValueType)
			{
				text = "struct";
			}
			stringBuilder.AppendLine("public " + text + " " + ((MemberReference)typeDef).Name + " // Simplified declaration");
			stringBuilder.AppendLine("{");
			List<FieldDefinition> list = ((IEnumerable<FieldDefinition>)typeDef.Fields).ToList();
			if (list.Any())
			{
				stringBuilder.AppendLine("  // Fields");
				foreach (FieldDefinition item in list.Take(10))
				{
					stringBuilder.AppendLine("  " + GetFieldVisibility(item) + " " + (item.IsStatic ? "static " : "") + ((MemberReference)((FieldReference)item).FieldType).Name + " " + ((MemberReference)item).Name + ";");
				}
				if (list.Count > 10)
				{
					stringBuilder.AppendLine($"  // ... and {list.Count - 10} more fields");
				}
				stringBuilder.AppendLine();
			}
			List<PropertyDefinition> list2 = ((IEnumerable<PropertyDefinition>)typeDef.Properties).ToList();
			if (list2.Any())
			{
				stringBuilder.AppendLine("  // Properties");
				foreach (PropertyDefinition item2 in list2.Take(10))
				{
					string text2 = "{ ";
					if (item2.GetMethod != null)
					{
						text2 += "get; ";
					}
					if (item2.SetMethod != null)
					{
						text2 += "set; ";
					}
					text2 += "}";
					MethodDefinition getMethod = item2.GetMethod;
					int num;
					if (getMethod == null || !getMethod.IsStatic)
					{
						MethodDefinition setMethod = item2.SetMethod;
						num = ((setMethod != null && setMethod.IsStatic) ? 1 : 0);
					}
					else
					{
						num = 1;
					}
					bool flag = (byte)num != 0;
					stringBuilder.AppendLine("  " + GetPropertyVisibility(item2) + " " + (flag ? "static " : "") + ((MemberReference)((PropertyReference)item2).PropertyType).Name + " " + ((MemberReference)item2).Name + " " + text2);
				}
				if (list2.Count > 10)
				{
					stringBuilder.AppendLine($"  // ... and {list2.Count - 10} more properties");
				}
				stringBuilder.AppendLine();
			}
			List<MethodDefinition> list3 = ((IEnumerable<MethodDefinition>)typeDef.Methods).Where((MethodDefinition m) => !m.IsConstructor && !m.IsSpecialName).ToList();
			if (list3.Any())
			{
				stringBuilder.AppendLine("  // Methods (signatures only, excluding constructors/property accessors)");
				foreach (MethodDefinition item3 in list3.Take(15))
				{
					string text3 = ((highlightMethodName != null && ((MemberReference)item3).Name == highlightMethodName) ? " // <<< Method with finding" : "");
					stringBuilder.AppendLine("  " + GetMethodVisibility(item3) + " " + (item3.IsStatic ? "static " : "") + ((MemberReference)((MethodReference)item3).ReturnType).Name + " " + ((MemberReference)item3).Name + "(" + GetMethodParameters(item3) + ");" + text3);
				}
				if (list3.Count > 15)
				{
					stringBuilder.AppendLine($"  // ... and {list3.Count - 15} more methods");
				}
			}
			stringBuilder.AppendLine("}");
			return stringBuilder.ToString();
		}

		private string GetMethodVisibility(MethodDefinition method)
		{
			if (method.IsPublic)
			{
				return "public";
			}
			if (method.IsPrivate)
			{
				return "private";
			}
			if (method.IsFamily)
			{
				return "protected";
			}
			if (method.IsFamilyOrAssembly)
			{
				return "protected internal";
			}
			return "internal";
		}

		private string GetMethodParameters(MethodDefinition method)
		{
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			List<string> list = new List<string>();
			Enumerator<ParameterDefinition> enumerator = ((MethodReference)method).Parameters.GetEnumerator();
			try
			{
				while (enumerator.MoveNext())
				{
					ParameterDefinition current = enumerator.Current;
					list.Add(((MemberReference)((ParameterReference)current).ParameterType).Name + " " + ((ParameterReference)current).Name);
				}
			}
			finally
			{
				((IDisposable)enumerator).Dispose();
			}
			return string.Join(", ", list);
		}

		private string FormatInstruction(Instruction instruction)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			OpCode opCode = instruction.OpCode;
			string name = ((OpCode)(ref opCode)).Name;
			if (name == "nop")
			{
				return string.Empty;
			}
			string text = FormatOperand(instruction.Operand);
			return (name + " " + text).Trim();
		}

		private string FormatOperand(object operand)
		{
			if (operand == null)
			{
				return string.Empty;
			}
			MethodReference val = (MethodReference)((operand is MethodReference) ? operand : null);
			if (val != null)
			{
				return ((MemberReference)((MemberReference)val).DeclaringType).Name + "." + ((MemberReference)val).Name + "()";
			}
			TypeReference val2 = (TypeReference)((operand is TypeReference) ? operand : null);
			if (val2 != null)
			{
				return ((MemberReference)val2).FullName;
			}
			FieldReference val3 = (FieldReference)((operand is FieldReference) ? operand : null);
			if (val3 != null)
			{
				return ((MemberReference)((MemberReference)val3).DeclaringType).Name + "." + ((MemberReference)val3).Name;
			}
			if (operand is string text)
			{
				return "\"" + text + "\"";
			}
			return operand.ToString();
		}

		private string ExtractAssemblyMetadata(string modPath)
		{
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Expected O, but got Unknown
			try
			{
				if (!File.Exists(modPath))
				{
					return string.Empty;
				}
				StringBuilder stringBuilder = new StringBuilder();
				ReaderParameters val = new ReaderParameters
				{
					ReadWrite = false,
					InMemory = true,
					ReadSymbols = false
				};
				AssemblyDefinition val2 = AssemblyDefinition.ReadAssembly(modPath, val);
				try
				{
					stringBuilder.AppendLine("- **Assembly Name**: " + ((AssemblyNameReference)val2.Name).Name);
					stringBuilder.AppendLine($"- **Version**: {((AssemblyNameReference)val2.Name).Version}");
					if (!string.IsNullOrEmpty(((AssemblyNameReference)val2.Name).Culture))
					{
						stringBuilder.AppendLine("- **Culture**: " + ((AssemblyNameReference)val2.Name).Culture);
					}
					stringBuilder.AppendLine("- **Referenced Assemblies**:");
					foreach (AssemblyNameReference item in ((IEnumerable<AssemblyNameReference>)val2.MainModule.AssemblyReferences).Take(10))
					{
						stringBuilder.AppendLine($"  - {item.Name} (v{item.Version})");
					}
					if (val2.MainModule.AssemblyReferences.Count > 10)
					{
						stringBuilder.AppendLine($"  - *and {val2.MainModule.AssemblyReferences.Count - 10} more...*");
					}
					List<CustomAttribute> list = ((IEnumerable<CustomAttribute>)val2.CustomAttributes).Where((CustomAttribute attr) => ((MemberReference)attr.AttributeType).Name.Contains("Security") || ((MemberReference)attr.AttributeType).Name.Contains("Permission") || ((MemberReference)attr.AttributeType).Name.Contains("Unsafe")).ToList();
					if (list.Any())
					{
						stringBuilder.AppendLine("- **Security-Related Attributes**:");
						foreach (CustomAttribute item2 in list)
						{
							stringBuilder.AppendLine("  - " + ((MemberReference)item2.AttributeType).Name);
						}
					}
					return stringBuilder.ToString();
				}
				finally
				{
					((IDisposable)val2)?.Dispose();
				}
			}
			catch (Exception ex)
			{
				_logger.Error("Failed to extract assembly metadata from " + modPath + ": " + ex.Message);
				return string.Empty;
			}
		}

		public bool SavePromptToFile(string modPath, List<ScanFinding> findings, string outputDirectory)
		{
			try
			{
				string contents = GeneratePrompt(modPath, findings);
				string fileName = Path.GetFileName(modPath);
				Directory.CreateDirectory(outputDirectory);
				File.WriteAllText(Path.Combine(outputDirectory, fileName + ".prompt.md"), contents);
				return true;
			}
			catch (Exception ex)
			{
				_logger.Error("Failed to save prompt to file: " + ex.Message);
				return false;
			}
		}

		private static string FormatSeverityLabel(Severity severity)
		{
			return severity switch
			{
				Severity.Critical => "CRITICAL", 
				Severity.High => "HIGH", 
				Severity.Medium => "MEDIUM", 
				Severity.Low => "LOW", 
				_ => severity.ToString().ToUpper(), 
			};
		}
	}
}
namespace MLVScan.Adapters
{
	public class MelonScanLogger : IScanLogger
	{
		private readonly Instance _logger;

		public MelonScanLogger(Instance logger)
		{
			_logger = logger ?? throw new ArgumentNullException("logger");
		}

		public void Debug(string message)
		{
			_logger.Msg("[DEBUG] " + message);
		}

		public void Info(string message)
		{
			_logger.Msg(message);
		}

		public void Warning(string message)
		{
			_logger.Warning(message);
		}

		public void Error(string message)
		{
			_logger.Error(message);
		}

		public void Error(string message, Exception exception)
		{
			_logger.Error($"{message}: {exception}");
		}
	}
	public class GameAssemblyResolverProvider : IAssemblyResolverProvider
	{
		public IAssemblyResolver CreateResolver()
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Expected O, but got Unknown
			DefaultAssemblyResolver val = new DefaultAssemblyResolver();
			try
			{
				string text = Path.Combine(MelonEnvironment.GameRootDirectory, Path.GetFileNameWithoutExtension(MelonEnvironment.GameExecutablePath) + "_Data", "Managed");
				if (Directory.Exists(text))
				{
					((BaseAssemblyResolver)val).AddSearchDirectory(text);
				}
				string text2 = Path.Combine(MelonEnvironment.GameRootDirectory, "MelonLoader", "net35");
				if (Directory.Exists(text2))
				{
					((BaseAssemblyResolver)val).AddSearchDirectory(text2);
				}
				string text3 = Path.Combine(MelonEnvironment.GameRootDirectory, "MelonLoader", "net6");
				if (Directory.Exists(text3))
				{
					((BaseAssemblyResolver)val).AddSearchDirectory(text3);
				}
				string modsDirectory = MelonEnvironment.ModsDirectory;
				if (Directory.Exists(modsDirectory))
				{
					((BaseAssemblyResolver)val).AddSearchDirectory(modsDirectory);
				}
				string pluginsDirectory = MelonEnvironment.PluginsDirectory;
				if (Directory.Exists(pluginsDirectory))
				{
					((BaseAssemblyResolver)val).AddSearchDirectory(pluginsDirectory);
				}
			}
			catch (Exception)
			{
			}
			return (IAssemblyResolver)(object)val;
		}
	}
}
namespace MLVScan.Models
{
	public class DisabledModInfo
	{
		public string OriginalPath { get; }

		public string DisabledPath { get; }

		public string FileHash { get; }

		public DisabledModInfo(string originalPath, string disabledPath, string fileHash)
		{
			OriginalPath = originalPath;
			DisabledPath = disabledPath