Skip to content

Repository files navigation

AnyProcess.Net

CI

AnyProcess.Net 1.0 unifica le funzionalità di Swed32 e Swed64 in una sola libreria AnyCPU per Windows, Linux e macOS. L'architettura viene rilevata dal processo target: una stessa applicazione a 64 bit può quindi gestire processi x86, x64, ARM e ARM64 senza scegliere un assembly differente.

Il progetto nasce dalle API dei progetti MIT Swed32 (Massivetwat, 2023) e Swed64 (Swedz, 2022), sostituendone l'implementazione Windows-only con backend nativi distinti dietro la stessa API.

Installazione

Richiede .NET 8 o una versione successiva compatibile:

dotnet add package AnyProcess.Net --version 1.0.0

Il pacchetto include assembly AnyCPU, documentazione XML per IntelliSense, README, changelog, licenza MIT e tutte le guide. Il pacchetto simboli .snupkg contiene PDB portabili con SourceLink verso l'esatto commit GitHub.

Funzionalità

  • lettura e scrittura di byte, numeri, booleani, caratteri, stringhe UTF-8, Vector3, matrici e puntatori;
  • API generiche per tipi unmanaged, overload TryRead/TryWrite e accesso diretto tramite Span<byte>/ReadOnlySpan<byte>;
  • lifecycle osservabile e thread safety durante accessi concorrenti, SetProcess e Dispose;
  • pooling dei buffer interni nei percorsi ad alta frequenza e benchmark riproducibili con BenchmarkDotNet;
  • pointer chain basate sulla dimensione puntatore del processo target;
  • enumerazione dei moduli e ricerca del loro indirizzo base;
  • enumerazione delle regioni di memoria con protezioni e tipo portabili;
  • scansione della memoria mappata con wildcard complete o per nibble;
  • signature scan compatibile con ScanForBytes32 di Swed32;
  • test su processi reali, non soltanto su buffer simulati;
  • CI su Windows x64, Linux x64/ARM64 e macOS Intel/Apple Silicon.

Esempio

using AnyProcess.Net;

using var memory = new ProcessMemory("my-process");

Console.WriteLine($"{memory.Architecture}, puntatori da {memory.PointerSize} byte");

var moduleBase = memory.GetModuleBase(
    OperatingSystem.IsWindows() ? "my-process.exe" : "my-process");
var health = memory.ReadInt(moduleBase + 0x1234);
memory.WriteInt(moduleBase + 0x1234, health + 10);

È possibile collegarsi anche tramite PID o System.Diagnostics.Process:

using var byPid = new ProcessMemory(1234);
using var byProcess = new ProcessMemory(System.Diagnostics.Process.GetCurrentProcess());

API robusta

using System.Runtime.InteropServices;

[StructLayout(LayoutKind.Sequential)]
struct PlayerState
{
    public int Health;
    public float Speed;
}

var state = memory.Read<PlayerState>(address);
state.Health = 100;
memory.Write(address, state);

Span<byte> header = stackalloc byte[16];
if (!memory.TryRead(address, header, out var error))
{
    Console.Error.WriteLine(
        $"{error!.Operation} PID {error.ProcessId}, errore nativo {error.NativeErrorCode}: " +
        error.NativeErrorMessage);
}

Le API Read e Write generano una ProcessMemoryException dettagliata se il sistema operativo rifiuta l'accesso. Le corrispondenti API TryRead e TryWrite restituiscono false e possono fornire la stessa diagnostica tramite un parametro out. Gli errori di programmazione, come l'uso di un oggetto già eliminato o un argomento non valido, continuano invece a generare un'eccezione.

La guida API robusta descrive layout dei tipi, span, compatibilità con le API storiche e proprietà diagnostiche.

Lifecycle e concorrenza

Console.WriteLine($"PID {memory.ProcessId}: {memory.LifecycleState}");

Parallel.For(0, 8, worker =>
{
    var value = memory.Read<int>(addresses[worker]);
    memory.Write(addresses[worker], value + 1);
});

if (!memory.IsAlive)
{
    Console.WriteLine("Il target non è più disponibile.");
}

Le operazioni indipendenti possono avanzare in parallelo. SetProcess e Dispose impediscono l'avvio di nuove operazioni, attendono quelle già in corso e solo dopo sostituiscono o chiudono le risorse native. La guida Lifecycle, thread safety e performance documenta ownership, pooling e benchmark.

Regioni e memory scanning

var regions = memory.GetMemoryRegions();

var matches = memory.ScanMemory(
    "48 8B ?? A? ?F 89",
    new MemoryScanOptions
    {
        RequireExecutable = true,
        MaxResults = 20
    });

Lo scanner legge soltanto regioni committed, leggibili e non guard. Lavora a blocchi mantenendo la sovrapposizione necessaria per trovare firme a cavallo tra due letture. La guida Regioni e scansione della memoria descrive wildcard, filtri, intervalli e differenze tra i sistemi operativi.

Permessi del sistema operativo

La compatibilità dell'API non elimina le protezioni del sistema operativo. Windows applica i diritti sugli handle di processo, Linux applica ptrace/Yama e macOS applica task port, code signing, Hardened Runtime e SIP.

La guida Permessi e protezioni descrive requisiti, diagnostica e limiti per ciascun sistema operativo.

Nop usa l'istruzione corretta per x86/x64 e ARM64. Su ARM32 l'esecuzione può essere ARM o Thumb, quindi va usato WriteBytes con l'encoding appropriato.

Un controller a 32 bit non può rappresentare tutti gli indirizzi di un target a 64 bit. Pubblicando l'applicazione chiamante come AnyCPU/64 bit, lo stesso assembly può controllare sia target a 32 bit sia target a 64 bit.

Stabilità della 1.0

La superficie pubblica della 1.0 è registrata in PublicAPI.Shipped.txt. Ogni build segnala come errore API aggiunte o rimosse senza un aggiornamento esplicito del contratto. Dalle versioni successive, dotnet pack confronta inoltre la compatibilità binaria del pacchetto con AnyProcess.Net 1.0.0 tramite Package Validation.

La guida Compatibilità dell'API descrive le regole per release patch, minor e major. La guida Pubblicazione documenta la checklist, SourceLink e la configurazione OIDC/Trusted Publishing di nuget.org.

Build e test

Richiede .NET 8 SDK:

dotnet restore AnyProcess.Net.sln
dotnet build AnyProcess.Net.sln --configuration Release --no-restore
dotnet test AnyProcess.Net.sln --configuration Release --no-build --no-restore

Il progetto AnyProcess.Net.TestTarget viene compilato con la solution ed è avviato dai test d'integrazione per verificare che le modifiche alla memoria siano osservate da un processo separato.

Per produrre il pacchetto NuGet 1.0.0 e il relativo .snupkg:

dotnet pack AnyProcess.Net/AnyProcess.Net.csproj --configuration Release
pwsh ./eng/Validate-NuGetPackage.ps1 -PackageDirectory AnyProcess.Net/bin/Release -Version 1.0.0

Per eseguire una sessione benchmark breve:

dotnet run --project AnyProcess.Net.Benchmarks -c Release -- --job short

About

Cross-platform .NET toolkit for process memory access, module inspection, code patching, and runtime manipulation.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages