XFE Git
XFE Studio Git
Git 首页 全局搜索
XFE 主站 文档 NuGet

XFEEDToolBox

【WinUI】XFE精英危险工具箱

公开
关注 0 Fork 0 Star 0
UTF-8
using System.Diagnostics;
using System.Reflection;
using System.Text.Json;
using XFEEDToolBox.Core.Native;
using XFEEDToolBox.Core.Navigation;

if(args.Length!=2)throw new ArgumentException("Use a verified game PID and a new report path.");
var pid=int.Parse(args[0]);var output=Path.GetFullPath(args[1]);if(File.Exists(output))throw new IOException("Use a fresh report.");
using var process=Process.GetProcessById(pid);var started=process.StartTime.ToUniversalTime().Ticks;
var type=typeof(IReadOnlyGameMemory).Assembly.GetType("XFEEDToolBox.Core.Native.ReadOnlyPlayerMemory",true)!;
using var lease=(IDisposable)Activator.CreateInstance(type,pid,started,NativeSystemLocationReader.GameSha256)!;
var memory=(IReadOnlyGameMemory)lease;var pipe=new NavigationPipeClient(pid);
ulong Pointer(ulong at)=>BitConverter.ToUInt64(memory.Read(at,8));
object Table(ulong pointer)
{
    var vtable=Pointer(pointer);
    if(vtable<memory.ImageBase||vtable>=memory.ImageBase+memory.ImageSize)throw new InvalidDataException("Vtable is outside the pinned image.");
    var methods=new Dictionary<string,string?>();
    for(ulong slot=0;slot<=0x180;slot+=8)
    {var method=Pointer(vtable+slot);methods[slot.ToString("x")]=method>=memory.ImageBase&&method<memory.ImageBase+memory.ImageSize?(method-memory.ImageBase).ToString("x"):null;}
    return new{pointer=pointer.ToString("x"),vtableRva=(vtable-memory.ImageBase).ToString("x"),methods};
}
object? evidence=null;string? failure=null;
using var timeout=new CancellationTokenSource(TimeSpan.FromMinutes(5));
try
{
    while(true)
    {
        timeout.Token.ThrowIfCancellationRequested();process.Refresh();if(process.HasExited||process.StartTime.ToUniversalTime().Ticks!=started)throw new IOException("Verified game exited.");
        try
        {
            var raw=await pipe.CallAsync(new{op="read"},timeout.Token);
            if(raw.TryGetProperty("inputOwnershipObservation",out var ownership)&&ownership.TryGetProperty("latest",out var latest)&&latest.ValueKind==JsonValueKind.Object
                &&latest.GetProperty("entityId").GetString()==raw.GetProperty("entityId").GetString()
                &&latest.GetProperty("nativeScoState").GetInt32()==2)
            {
                var root=Convert.ToUInt64(latest.GetProperty("inputRoot").GetString(),16);
                evidence=new{at=DateTimeOffset.UtcNow,rawSequence=raw.GetProperty("sequence").GetUInt64(),inputOwnership=ownership.Clone(),
                    mainInputRoot=Table(root),mainInputInterface=Table(checked(root+0x60))};break;
            }
        }
        catch(Exception error)when(error is IOException or InvalidOperationException){/* Readiness only; no input is sent. */}
        await Task.Delay(30,timeout.Token);
    }
}
catch(Exception error){failure=error.ToString();}
await File.WriteAllTextAsync(output,JsonSerializer.Serialize(new{pid,started,readOnly=true,processAccess="QUERY_INFORMATION|VM_READ",gameCallsMade=0,inputSent=0,evidence,failure},new JsonSerializerOptions{WriteIndented=true}));
Console.WriteLine(JsonSerializer.Serialize(new{captured=evidence is not null,output,failure}));