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

XFESystem

【Rust】XFE系统,基于Rust和汇编

公开
关注 0 Fork 0 Star 0
UTF-8
using System.Security.Cryptography;
using System.Text.Json;
using XFESystem.Storage;

namespace XFESystem.StorageFixtures;

public static class StorageReadback
{
    static void Require(bool condition,string message){if(!condition)throw new IOException(message);}
    public static void Verify(string directory,string token)
    {
        using var expected=JsonDocument.Parse(File.ReadAllBytes(Path.Combine(directory,"ExpectedOtherVolumes.json")));
        var mounts=expected.RootElement.EnumerateArray().ToArray();var proofs=new List<object>();
        foreach(string name in new[]{"NvmeNtfs","Nvme4K","SataExtended","UsbExFat"})
        {
            string source=Path.Combine(directory,"OtherDiskSeeds",name+".img"),actual=Path.Combine(directory,name+".img");
            using var original=new FixtureDisk(source,name,logicalSectorBytes:name=="Nvme4K"?4096:512);using var disk=new FixtureDisk(actual,name,logicalSectorBytes:name=="Nvme4K"?4096:512);
            var partitions=DiskPartitions.Read(original);Require(DiskPartitions.Read(disk).SequenceEqual(partitions),"Partition table changed: "+name);
            foreach(var partition in partitions)
            {
                var mount=mounts.Single(m=>m.GetProperty("Path").GetString()!.EndsWith("P"+partition.Number,StringComparison.Ordinal)&&
                    (name=="SataExtended"?m.GetProperty("Path").GetString()!.Contains("SATA"):name=="UsbExFat"?m.GetProperty("Path").GetString()!.Contains("USB"):m.GetProperty("Label").GetString()==name));
                string root=mount.GetProperty("Path").GetString()!,saved=token+"_"+root[(root.LastIndexOf('\\')+1)..];
                using var volume=new MountedVolume(disk,partition,root);Require(volume.Writable,"Filesystem dirty after cold boot: "+volume.ReadOnlyReason);
                Require(volume.ReadText(root+"\\EditMe.txt")==saved,"Existing-file overwrite did not persist");
                Require(volume.ReadText(root+"\\XfeProof\\Renamed.txt")==saved+"_appended","Append/rename did not persist");
                Require(!volume.Exists(root+"\\DeleteMe.txt")&&!volume.Exists(root+"\\XfeProof\\Keep.txt"),"Deletion/rename did not persist");
                byte[] program=volume.ReadBytes(root+"\\Programs\\External.dll"),copy=volume.ReadBytes(root+"\\XfeProof\\External.dll");Require(program.AsSpan().SequenceEqual(copy),"External managed PE changed");
                byte[] pattern=volume.ReadBytes(root+"\\Pattern.bin");Require(pattern.AsSpan().SequenceEqual(volume.ReadBytes(root+"\\XfeProof\\PatternCopy.bin")),"Multi-page DMA/file copy mismatch");
                proofs.Add(new{Disk=name,Partition=partition.Number,Root=root,FileSystem=volume.FileSystem,Clean=true,ReadWriteVerified=true,
                    SavedText=saved,ProgramSha256=Convert.ToHexStringLower(SHA256.HashData(copy)),PatternBytes=pattern.Length,PatternSha256=Convert.ToHexStringLower(SHA256.HashData(pattern))});
            }
            // Compare every byte outside all data partitions, including EBRs,
            // protective MBR, both GPT copies and gaps between logical volumes.
            ulong cursor=0;foreach(var partition in partitions.OrderBy(p=>p.Start))
            {Compare(original,disk,cursor,partition.Start-cursor);cursor=partition.Start+partition.Count;}
            Compare(original,disk,cursor,disk.SectorCount-cursor);Require(disk.Writes==0,"Readback tool modified its input");
        }
        var result=new{Kind="XfeIndependentOtherDiskHostReadback",Passed=true,HostOnly=true,GuestProgramExecutedByHost=false,PhysicalDiskAccess=false,
            ColdBootFilesVerified=true,OnlyPartitionSectorsChanged=true,AllVolumesClean=true,Volumes=proofs};
        File.WriteAllText(Path.Combine(directory,"OtherDiskReadback.json"),JsonSerializer.Serialize(result,new JsonSerializerOptions{WriteIndented=true}));
        Console.WriteLine(JsonSerializer.Serialize(result));
    }
    static void Compare(FixtureDisk a,FixtureDisk b,ulong start,ulong count)
    {
        while(count!=0){int sectors=(int)Math.Min(count,128);byte[] left=new byte[sectors*512],right=new byte[left.Length];a.Read(start,left);b.Read(start,right);Require(left.AsSpan().SequenceEqual(right),"Writes escaped a data partition");start+=(uint)sectors;count-=(uint)sectors;}
    }
}