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

XFEEDToolBox

【WinUI】XFE精英危险工具箱

公开
关注 0 Fork 0 Star 0
UTF-8
"""Original saved Power activity selector namespace, offline source only."""
import hashlib,importlib.util,json,struct
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)]
if hashes!=['6891f70a021fa9f3a0e00458c284f48d1226e68ae7fc02ad48081aed47857e93',
            'ed5a8f8cd10f9a80d3bda5badd7ba1d4fcfc15996c8c7e018852cb170e264b63']:raise ValueError('Power selector image changed')
functions=[];refs=[]
for before in [0x3A05660,0x3ACA1A0,0x3A6CDE0,0x3AB6760,0x3B46030,0x3ACF4A0]:
    span=old.function(before)
    if not span or span[0]!=before:raise ValueError('Exact selector function range missing')
    result=audit.match(old,new,before,span[1]-before)
    if result['status']!='unique':raise ValueError('Power selector complete source not unique: '+hex(before))
    result['oldRva']=hex(before);functions.append(result)
    refs+=audit.references(old,new,before,int(result['newRva'],16),result['length'])
slots=[]
for table,offset,target in [(0x551FFF0,0x3C8,0x3A6CDE0),(0x552D720,0x28,0x3B46030)]:
    mapped={r[1] for r in refs if r[0]==table}
    if len(mapped)!=1:raise ValueError('Actual selector vtable lacks a paired constructor operand')
    after=mapped.pop();function=next(f for f in functions if int(f['oldRva'],16)==target)
    if struct.unpack('<Q',old.data(table+offset,8))[0]-old.base!=target or \
       struct.unpack('<Q',new.data(after+offset,8))[0]-new.base!=int(function['newRva'],16):raise ValueError('Selector actual slot changed')
    slots.append(dict(oldVtable=hex(table),newVtable=hex(after),slot=hex(offset),oldFunction=hex(target),newFunction=function['newRva']))
evidence={}
for name in ['artifacts/galaxy-marker-research/map-as/scripts/components/leftHandPanels/PowerplayActivityPanelComponent.as',
             'artifacts/galaxy-query-research/power-selection/decompiled/3a6cde0.c',
             'artifacts/galaxy-query-research/power-selection/assembly/asm-full-3ab6760.txt',
             'artifacts/galaxy-query-research/filter-enums/decompiled/solo-3b46030.c',
             'artifacts/galaxy-query-research/filter-enums/decompiled/solo-3acf4a0.c']:
    evidence[name]=hashlib.sha256(Path(name).read_bytes()).hexdigest()
result=dict(runtimeNeutral=True,gameCalls=0,canInstallHooks=False,runtimeValidated=False,
    oldImageSha256=hashes[0],newImageSha256=hashes[1],functions=functions,actualTypedSlots=slots,evidenceSha256=evidence,
    conversion=dict(ui='powerID = definition Index+1',callback='3A6CDE0 subtracts1; bounds the result by actual definition count',
        transfer='3AB6760 copies optional first field unchanged to552D720+28/3B46030',
        saved='3B46030 writes low32 of first field to setting23; scopeMax becomes-2; disabled becomes-1',
        restore='3ACF4A0 sign-extends saved>=0 as original Index into optional field188; -2 restores All'),
    implementation='Pending index survives until exactly one actual definition row matches Index; then use that row name and InternalPowerId. Explicit user selection clears pending.',
    limits=['No original setters are invoked. No public list order, UiPowerId or InternalPowerId is used as the saved selector.'])
path=Path('artifacts/galaxy-query-research/power-selection/original-selector-evidence.json')
path.write_text(json.dumps(result,indent=2)+'\n',encoding='utf8')
print(json.dumps(dict(path=str(path),functions=len(functions),actualTypedSlots=slots),indent=2))