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

XFEEDToolBox

【WinUI】XFE精英危险工具箱

公开
关注 0 Fork 0 Star 0
UTF-8
"""Bounded original State classifier/owner proof. Offline PE bytes only."""
import hashlib,importlib.util,json
from pathlib import Path
spec=importlib.util.spec_from_file_location('audit',Path(__file__).with_name('Audit-GalaxyClientCompatibility.py'))
audit=importlib.util.module_from_spec(spec);spec.loader.exec_module(audit)
old=audit.Image(Path('artifacts/ship-model-reference/client-copy/EliteDangerous64.exe'))
new=audit.Image(Path('D:/SteamLibrary/steamapps/common/Elite Dangerous/Products/elite-dangerous-odyssey-64/EliteDangerous64.exe'))
hashes=[hashlib.sha256(i.raw).hexdigest() for i in (old,new)]
assert hashes==['6891f70a021fa9f3a0e00458c284f48d1226e68ae7fc02ad48081aed47857e93','ed5a8f8cd10f9a80d3bda5badd7ba1d4fcfc15996c8c7e018852cb170e264b63']
functions=[];references=[]
for before in [0x3ACCD20,0x3B262E0,0x3A0E740]:
    span=old.function(before);assert span and span[0]==before
    row=audit.match(old,new,before,span[1]-before);assert row['status']=='unique',row
    row['oldRva']=hex(before);functions.append(row)
    references.extend(audit.references(old,new,before,int(row['newRva'],16),row['length']))
binding={a:b for a,b,_,_ in references}
assert binding[0x5F5428C]==0x5F5428C
slots=[]
for table,offset in [(0x552DE90,0x28),(0x552DE90,0x30),(0x552DE90,0x50),(0x55278C0,0x38)]:
    before=int.from_bytes(old.data(table+offset,8),'little')-old.base
    after=int.from_bytes(new.data(binding[table]+offset,8),'little')-new.base
    span=old.function(before)
    if span and span[0]==before:length=span[1]-before
    else:
        ins=[]
        for item in old.instructions(before,256):
            ins.append(item)
            if item.mnemonic=='ret':break
        assert ins[-1].mnemonic=='ret';length=sum(i.size for i in ins)
    left,mask,*_=audit.signature(old,before,length);right,other,*_=audit.signature(new,after,length)
    assert len(left)==length and mask==other and all(a==b for a,b,k in zip(left,right,mask) if k)
    functions.append(dict(oldRva=hex(before),newRva=hex(after),length=length,status='unique',method='actual-ctor-paired-vtable-slot-and-full-body'))
    references.extend(audit.references(old,new,before,after,length))
    slots.append(dict(oldVtable=hex(table),newVtable=hex(binding[table]),slot=hex(offset),oldRva=hex(before),newRva=hex(after),length=length))
assert old.data(0x2DB040,8)==bytes.fromhex('488d8188020000c3')
# The classifier's actual direct call, rather than a similar hash function,
# binds the u64-address membership leaf. Its complete RET-delimited body is
# checked in both files. This leaf has no native call in the adapter.
after={a:b for a,b,_,_ in references}[0x627800]
leaf=[]
for item in old.instructions(0x627800,256):
    leaf.append(item)
    if item.mnemonic=='ret':break
body=old.instructions(0x627800,0x100)
# No unwind entry for this leaf. It has two returns; the second closes the
# positive membership branch at +73. Bytes after it are alignment, not code.
returns=[i for i in body if i.mnemonic=='ret']
assert returns[1].address-old.base==0x627873
length=0x74
# There are no external operands. Every branch is local, so the full bytes,
# including both return paths, must be literally identical without a mask.
assert old.data(0x627800,length)==new.data(after,length)
functions.append(dict(oldRva='0x627800',newRva=hex(after),length=length,status='unique',method='actual-classifier-paired-direct-call-and-full-body',
 rawLeafWholeBody=True,oldWindowSha256=hashlib.sha256(old.data(0x627800,length)).hexdigest(),newWindowSha256=hashlib.sha256(new.data(after,length)).hexdigest()))
references.extend(audit.references(old,new,0x627800,after,length))
result=dict(runtimeNeutral=True,gameProcessAccess=False,gameCalls=0,networkRequests=0,runtimeValidated=False,
 oldImageSha256=hashes[0],newImageSha256=hashes[1],functions=functions,references=[list(map(hex,row)) for row in references],slots=slots,
 vtables=[dict(oldRva=hex(v),newRva=hex(binding[v])) for v in [0x552DE90,0x55276E8,0x5527718,0x55278C0]],
 classification=dict(originalFunction='0x3b262e0',setSource='registered5F5428C interface+288 = manager+2F8',
  positiveMembershipState=39,positiveMembershipName='Unpopulated',otherwise='actual metadata descriptor+1C, missing descriptor0; missing compact14',
  noInventedReadyFlags=True,unknown='Uninitialized/unreadable owner or membership stays unknown; no public/BGS fallback.'),
 palette=dict(provider='MainUI+288 shared controller; State handle controller+300/+308',category=6,
  table='provider+90 count,+98 capacity,+A0 bit storage',stride=56,rawKey=0,settingsName=16,rawRgba=32,
  gameSelectionIgnored=['row+30 selected','row+34 animation'],noAdditionalFrontlineOverlayObserved=True))
out=Path('artifacts/galaxy-query-research/state-facts/compatibility.json');out.parent.mkdir(parents=True,exist_ok=True)
out.write_text(json.dumps(result,indent=2)+'\n',encoding='utf8')
print(json.dumps(dict(output=str(out),functions=[{k:r[k] for k in ['oldRva','newRva','length']} for r in functions],slots=slots),indent=2))