Llama.Memory 1.0.3

dotnet add package Llama.Memory --version 1.0.3
                    
NuGet\Install-Package Llama.Memory -Version 1.0.3
                    
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="Llama.Memory" Version="1.0.3" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Llama.Memory" Version="1.0.3" />
                    
Directory.Packages.props
<PackageReference Include="Llama.Memory" />
                    
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 Llama.Memory --version 1.0.3
                    
#r "nuget: Llama.Memory, 1.0.3"
                    
#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 Llama.Memory@1.0.3
                    
#: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=Llama.Memory&version=1.0.3
                    
Install as a Cake Addin
#tool nuget:?package=Llama.Memory&version=1.0.3
                    
Install as a Cake Tool

Llama.Memory

NuGet Version NuGet Downloads

Llama.Memory is a lightweight byte-pattern scanning and PE header utility library for .NET.

It provides GreyMagic-style pattern strings with wildcard bytes and post-match cursor commands, plus a dependency-free PE header parser for locating image sections in unmanaged memory snapshots or raw executable files.


Features

  • Pattern searching: Scans contiguous byte buffers using Span<T>, SearchValues<T>, and optimized anchor selection.
  • Multi-pattern scanning: Resolves the first hit for each pattern, or all hits for each pattern, in one scanner call.
  • PE header parsing: Reads DOS/NT headers, image base, and section data without third-party PE parsing dependencies.
  • Cursor commands in patterns: Append address adjustment, reads, and relative tracing commands after the byte pattern.
  • Unmanaged memory support: UnmanagedMemoryManager<T> can wrap raw unmanaged memory as Memory<T> for APIs that consume Memory<T>.

Pattern Format

Patterns are space-separated tokens:

{hex bytes and wildcards} {optional commands}

Wildcard bytes can be written as ?? or ?. Half-byte wildcards such as 4? and ?F are also accepted.

Commands are executed sequentially after the initial byte pattern is matched:

  • Add # - Shifts the result pointer forward by # bytes. Decimal and hex operands are supported.
  • Sub # - Shifts the result pointer backward by # bytes. Decimal and hex operands are supported.
  • Read8 - Reads one byte from the current result offset.
  • Read16 - Reads a little-endian Int16 from the current result offset.
  • Read32 - Reads a little-endian Int32 from the current result offset.
  • Read64 - Reads a little-endian Int64 from the current result offset.
  • TraceRelative - Reads a 32-bit relative displacement at the current result offset and returns current + 4 + displacement + ImageBase.
  • TraceCall - Resolves an E8 rel32-style call by reading the 32-bit displacement at current + 1 and returning current + 5 + displacement + ImageBase.

Example:

48 8D 0D ? ? ? ? E8 ? ? ? ? 48 8B F0 48 85 C0 74 ? 48 83 38 Add 3 TraceRelative

Usage Examples

Offline Analysis From a File

using Llama.Memory;

var peHeader = PeHeaderParser.GetPeHeaders(@"ffxiv_dx11.exe");
var textSection = peHeader.TextSection
    ?? throw new InvalidDataException("The PE file does not contain a .text section.");

var fileBytes = File.ReadAllBytes(@"ffxiv_dx11.exe");
var sectionData = fileBytes.AsMemory(
    checked((int)textSection.PointerToRawData),
    checked((int)textSection.SizeOfRawData));

var scanner = new PatternSearcher(
    sectionData,
    new IntPtr(textSection.VirtualAddress));

var result = scanner.Search(
    "48 8D 0D ? ? ? ? E8 ? ? ? ? 48 8B F0 48 85 C0 74 ? 48 83 38 Add 3 TraceRelative");

Console.WriteLine($"Match found at: 0x{result.ToInt64():X}");

The ImageBase constructor argument is added to raw match offsets when results are returned. For PE section scans, pass the section VirtualAddress if you want returned values expressed as RVAs for that section.

Live Memory Snapshot

For an external process, read the target memory range into a byte buffer first, then scan that buffer:

using System.Diagnostics;
using Llama.Memory;

var process = Process.GetCurrentProcess();
var module = process.MainModule
    ?? throw new InvalidOperationException("The process has no main module.");

var memorySize = module.ModuleMemorySize;
var baseAddress = module.BaseAddress;
var bytes = new byte[memorySize];

// Fill 'bytes' with the target range, for example via ReadProcessMemory.

var scanner = new PatternSearcher(bytes, baseAddress);

var result = scanner.Search(
    "48 8D 0D ? ? ? ? E8 ? ? ? ? 48 8B F0 48 85 C0 74 ? 48 83 38 Add 3 TraceRelative");

For an internal or injected scenario with an unmanaged pointer, wrap the pointer in UnmanagedMemoryManager<byte> and pass its Memory to PatternSearcher.

API Reference

PatternSearcher

Constructors:

  • PatternSearcher(byte[] assemblyData, IntPtr imageBase)
  • PatternSearcher(Span<byte> assemblyData, IntPtr imageBase)
  • PatternSearcher(ref ReadOnlySpan<byte> assemblyData, IntPtr imageBase)
  • PatternSearcher(ReadOnlySpan<byte> assemblyData, IntPtr imageBase)
  • PatternSearcher(Memory<byte> assemblyData, IntPtr imageBase)

Search methods:

  • IntPtr Search(string pattern) - Returns the first transformed match, or IntPtr.Zero.
  • IntPtr Search(string pattern, IntPtr start, int maxSearchLength) - Returns the first transformed match in a raw buffer sub-range. start is a zero-based buffer offset, not an address with ImageBase already applied.
  • IntPtr[] SearchMany(string pattern) - Returns every transformed match for one pattern.
  • IntPtr[] Search(string[] patterns) - Returns the first transformed match for each pattern. Results are index-aligned with the input array.
  • IntPtr[][] SearchMany(string[] patterns) - Returns every transformed match for each pattern. Results are index-aligned with the input array.
  • ReadOnlySpan<byte> GetSlice(int start, int length) - Returns a read-only span over a raw buffer sub-range.

PeHeaderParser

  • PeHeaderInfo GetPeHeaders(string filePath) - Parses the PE headers and returns the image base plus all section headers.
  • uint RvaToFileOffset(uint rva, SimpleSectionHeader[] sections) - Converts an RVA to a file offset using the parsed section table.

PeHeaderInfo

PeHeaderInfo contains:

  • ulong ImageBase
  • SimpleSectionHeader[] Sections
  • SimpleSectionHeader this[int index]
  • SimpleSectionHeader? TextSection
  • SimpleSectionHeader? RdataSection
  • SimpleSectionHeader? DataSection

SimpleSectionHeader

Represents a PE section with:

  • Name
  • VirtualSize
  • VirtualAddress
  • SizeOfRawData
  • PointerToRawData

FfxivVersionChecker

  • (string Version, string Date) GetVersion(FileInfo ffxivExe) - Reads the expected version marker from the data section.
  • (string Version, string Date) GetVersionPattern(FileInfo ffxivExe) - Locates the version marker via pattern scanning, then reads and parses it.

UnmanagedMemoryManager<T>

Wraps an unmanaged pointer and length as a Memory<T> source. The caller owns the lifetime of the unmanaged memory.

Product Compatible and additional computed target framework versions.
.NET net8.0 is compatible.  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 is compatible.  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. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.
  • net10.0

    • No dependencies.
  • net8.0

    • No dependencies.

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.0.3 94 5/18/2026
1.0.2 92 5/14/2026
1.0.1 99 5/6/2026
1.0.0 99 5/6/2026