MLVScan.Core 1.9.1

dotnet add package MLVScan.Core --version 1.9.1
                    
NuGet\Install-Package MLVScan.Core -Version 1.9.1
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="MLVScan.Core" Version="1.9.1" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="MLVScan.Core" Version="1.9.1" />
                    
Directory.Packages.props
<PackageReference Include="MLVScan.Core" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add MLVScan.Core --version 1.9.1
                    
#r "nuget: MLVScan.Core, 1.9.1"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package MLVScan.Core@1.9.1
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=MLVScan.Core&version=1.9.1
                    
Install as a Cake Addin
#tool nuget:?package=MLVScan.Core&version=1.9.1
                    
Install as a Cake Tool

MLVScan.Core

Tests codecov NuGet npm

MLVScan.Core is a cross-platform malware detection engine for .NET assemblies, powered by IL analysis with Mono.Cecil. It serves as the scanning backbone for MLVScan (MelonLoader, BepInEx 5.x, and BepInEx 6.x Mono/Il2Cpp), MLVScan.DevCLI, and MLVScan.Web through the @mlvscan/wasm-core package.

Why MLVScan?

Most modders download mods from trusted sites like Thunderstore or NexusMods, where files are typically already scanned by VirusTotal. This catches most plain viruses, but sophisticated threats often slip through.

MLVScan acts as your second line of defense. It specifically targets:

  • Virus loaders: malicious DLLs designed to download additional payloads.
  • Obfuscation techniques: code that hides its true purpose from standard AV.
  • Stealthy payloads: threats that do not match known signatures.

Think of it as the checkpoint after VirusTotal: catching what traditional scanners miss.

Installation

dotnet add package MLVScan.Core

Quick Usage

using MLVScan;
using MLVScan.Models.Dto;
using MLVScan.Services;

var rules = RuleFactory.CreateDefaultRules();
var scanner = new AssemblyScanner(rules);
var assemblyPath = "path/to/suspicious.dll";
var assemblyBytes = File.ReadAllBytes(assemblyPath);
var findings = scanner.Scan(assemblyPath).ToList();
var result = ScanResultMapper.ToDto(
    findings,
    Path.GetFileName(assemblyPath),
    assemblyBytes,
    new ScanResultOptions
    {
        Platform = "my-tool",
        PlatformVersion = "1.0.0"
    });

Console.WriteLine($"{result.Disposition?.Classification}: {result.Disposition?.Headline}");

if (result.ThreatFamilies?.Count > 0)
{
    foreach (var family in result.ThreatFamilies)
    {
        Console.WriteLine($"Matched family: {family.DisplayName} ({family.FamilyId})");
    }
}

foreach (var finding in result.Findings)
{
    Console.WriteLine($"[{finding.Severity}] {finding.RuleId}: {finding.Description}");
}

The scanner emits rule findings as the foundational evidence, but the primary verdict comes from the threat-intel layer: matched threatFamilies and the final disposition built on top of those findings.

A Suspicious disposition can carry blockingRecommended: false. Currently this is limited to a verified local restart script: a bounded IL analysis binds the written script to its encoded, detached PowerShell launcher. The accepted script waits for the current process and launches a literal steam://run/<app-id> URI, with optional logging, bounded delays/retry, and non-recursive *.delete cleanup. The original execution findings remain visible. This is advisory review, not a clean verdict or a guarantee about other code in the assembly.

Unknown script operations, unresolved launch bindings, additional high-risk findings, suspicious data flows, incomplete analysis, or known threat-family matches prevent this advisory classification. The recognizer does not use file hashes, mod names, method names, or game-specific IDs. Unsupported restart implementations retain the existing classification.

Process argument resolution follows bounded Encoding.GetBytes/Convert.ToBase64String, Convert.FromBase64String/Encoding.GetString, and string replacement chains. Recovered PowerShell encoded commands participate in detection and appear in finding descriptions, including CLI output. Runtime-dependent values remain explicitly partial; competing local assignments retain their possible values instead of selecting the nearest store. Recovery has size, work, and depth limits and never executes sample code. This improves evidence coverage; it is not a guarantee that every runtime command can be reconstructed.

For the supported detached PowerShell launcher, a proven binding to a local WriteAllText also exposes the written script body to detection and reporting. Script binding and restart approval are separate: a bound script containing additional operations stays visible and must still pass the closed restart grammar before it can receive an advisory disposition.

Conflicting helper returns and observed mutable-field writes retain bounded alternatives, including unresolved values. Supported encoding transforms preserve those alternatives separately. Field observations do not establish receiver identity or runtime write order; search limits are reported explicitly. Possible dangerous process targets remain detection evidence even when another alternative names a legitimate tool.

Deep analysis modes

ScanConfig.DeepScanMode controls when larger, still finite analysis budgets are used:

using MLVScan.Models;

var config = new ScanConfig { DeepScanMode = DeepScanMode.RetryOnIncomplete };
var scanner = new AssemblyScanner(RuleFactory.CreateDefaultRules(), config);
var findings = scanner.Scan(assemblyPath).ToList();
var modeUsed = scanner.LastScanUsedDeepAnalysis ? "deep" : "standard";

Disabled is the default single pass. RetryOnIncomplete runs a second pass when data-flow analysis or process value recovery reaches a configured limit. Always uses deep budgets from the start. Deep analysis increases call depth, data-flow budgets, and process value recovery budgets; it can take longer and can still report incomplete analysis if a higher limit is reached. Hosts should report deep as the result scan mode when LastScanUsedDeepAnalysis is true.

Process recovery defaults to 4,096 work units, depth 32, and 32 alternatives. Deep mode raises these to at least 65,536, 64, and 128 respectively. MaxValueResolutionWork, MaxValueResolutionDepth, and MaxValueResolutionAlternatives configure these finite budgets. Conflicting returns and mutable field writes remain uncertain in every mode; increasing a budget never makes an ambiguous value concrete.

ValueResolutionBudget is an advanced diagnostic for partial process-value recovery. It triggers retry mode and retains the candidates recovered so far. It does not, by itself, establish malicious behavior or mean that assembly instructions were skipped. Deep analysis can still reach a limit or encounter values that depend on runtime input.

Documentation

Complete documentation is available in the MLVScan.Core docs.

Features

  • Platform agnostic: works on Windows, Linux, and WebAssembly.
  • Multi-signal detection: context-aware analysis reduces false positives.
  • Stream support: scan files from memory without writing to disk.
  • Deep behavior analysis: correlates practical decode, load, and execute behavior chains in compiled code.

Licensed under GPL-3.0.

Product Compatible and additional computed target framework versions.
.NET net5.0 was computed.  net5.0-windows was computed.  net6.0 was computed.  net6.0-android was computed.  net6.0-ios was computed.  net6.0-maccatalyst was computed.  net6.0-macos was computed.  net6.0-tvos was computed.  net6.0-windows was computed.  net7.0 was computed.  net7.0-android was computed.  net7.0-ios was computed.  net7.0-maccatalyst was computed.  net7.0-macos was computed.  net7.0-tvos was computed.  net7.0-windows was computed.  net8.0 was computed.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed.  net9.0 was computed.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 was computed.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
.NET Core netcoreapp3.0 was computed.  netcoreapp3.1 was computed. 
.NET Standard netstandard2.1 is compatible. 
MonoAndroid monoandroid was computed. 
MonoMac monomac was computed. 
MonoTouch monotouch was computed. 
Tizen tizen60 was computed. 
Xamarin.iOS xamarinios was computed. 
Xamarin.Mac xamarinmac was computed. 
Xamarin.TVOS xamarintvos was computed. 
Xamarin.WatchOS xamarinwatchos was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
1.9.1 0 10/28/2026
1.9.0 498 9/25/2026
1.8.3 132 9/23/2026
1.8.2 156 9/20/2026
1.8.0 383 8/28/2026
1.7.2 979 6/20/2026
1.7.1 229 6/13/2026
1.7.0 280 6/1/2026
1.6.0 191 5/28/2026
1.5.0 275 5/18/2026
1.4.1 289 5/5/2026
1.4.0 369 4/17/2026
1.3.8 305 4/4/2026
1.3.7 170 4/3/2026
1.3.6 302 3/23/2026
1.3.5 140 3/23/2026
1.3.4 152 3/23/2026
1.3.3 171 3/21/2026
1.3.2 144 3/21/2026
1.3.1 152 3/20/2026
Loading failed