Using CILFI Programmatically
The core parsing and matching engine of CILFI (CilFi.Core) can be reused as a library.
Note that CILFI uses AsmResolver as its .NET metadata backend. As such, some proficiency with the library is recommended when trying to use the API of CILFI.
Compiling signatures
To compile a CILFI signature, use the SignatureCompiler class:
using CilFi.Compiler;
var result = SignatureCompiler.CompileFile(@"C:\path\to\signatures.cilfi");
var result = SignatureCompiler.CompileSnippet(
"""
.signature MySignature
{
.method static void ??() cil managed
{
.block $block1
{
ldstr "Hello, CILFI!"
call void [mscorlib] System.Console::WriteLine(string)
}
}
}
"""
);
When compilation succeeds, all the parsed and compiled signatures will appear in the Signatures property of the result.
if (result.IsSuccess)
{
foreach (var signature in result.Signatures)
{
Console.WriteLine(signature.Name);
// ...
}
}
Inspecting any compiler messages (i.e., compilation warnings and errors) can be done through the Diagnostics property:
foreach (var diagnostic in result.Diagnostics)
{
Console.WriteLine($"[{diagnostic.Level}] (Line: {diagnostic.Line}, Column: {diagnostic.Column}) {diagnostic.Message}");
}
Using signatures
There are two ways to use Signature objects.
The simplest way is to use a SignatureMatcher, which can be used to easily query an entire ModuleDefinition for matches:
using CilFi;
using AsmResolver.DotNet;
Signature signature = ...
string binaryPath = ...;
var module = ModuleDefinition.FromFile(binaryPath);
var result = SignatureMatcher.MatchInModule(module, [signature]);
foreach (var match in result.Matches)
{
Console.WriteLine($"{match.Method}: {match.Signature.Name}");
}
Alternatively, signatures can also be used directly for more control over the matching process:
using CilFi;
using AsmResolver.DotNet;
Signature signature = ...
string binaryPath = ...;
var module = ModuleDefinition.FromFile(binaryPath);
foreach (var method in module.GetAllTypes().SelectMany(t => t.Methods))
{
if (signature.Pattern.Match(method, context) is { } match)
{
// `method` matches `signature`
}
}