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

XFEEDToolBox

【WinUI】XFE精英危险工具箱

公开
关注 0 Fork 0 Star 0
UTF-8
"""Bounded original size-channel evidence. Offline PE/resources only, no game calls."""
import hashlib,json,re,struct
from pathlib import Path
import pefile
from capstone import Cs,CS_ARCH_X86,CS_MODE_64

root=Path(__file__).resolve().parents[1]
image=root/'artifacts/ship-model-reference/client-copy/EliteDangerous64.exe'
digest=hashlib.sha256(image.read_bytes()).hexdigest()
assert digest=='6891f70a021fa9f3a0e00458c284f48d1226e68ae7fc02ad48081aed47857e93'
pe=pefile.PE(str(image),fast_load=True);base=pe.OPTIONAL_HEADER.ImageBase
cs=Cs(CS_ARCH_X86,CS_MODE_64)
categories=['None','Population','Allegiance','Government','Economy','StarClass','State','Security','Visited','Commodity','Civilization','Services','FleetCarrier','Colonisation','Exploration','TradeData']
ctors=[0x3acd8d0,0x3acf6b0,0x3ac56a0,0x3acbca0,0x3ac41d0,0x3ad2c70,0x3accd20,0x3ad0bf0,0x3ad9790,0x3ac3c20,0x3ad1f00,0x3ad17f0,0x3ac5ff0,0x3acefa0,0x3ac4cf0,0x3ad86e0]
rows=[]
for index,(category,ctor) in enumerate(zip(categories,ctors)):
    files=sorted((root/'artifacts/galaxy-query-research').rglob(f'*{ctor:x}.c'))
    assert files,(category,'missing constructor')
    text=files[0].read_text(encoding='utf8')
    vtables=re.findall(r'\*param_1 = &UNK_14([0-9a-f]+);',text)
    assert vtables,(category,'missing derived vtable')
    vt=int(vtables[-1],16)
    function=struct.unpack('<Q',pe.get_data(vt+0x48,8))[0]-base
    expected=0x3b27ef0 if index==0 else 0x3b27fa0 if index==1 else 0x3b27eb0 if index==9 else 0x3b27f00 if index==13 else 0x3b28160
    assert function==expected,(category,hex(function))
    ins=[]
    for i in cs.disasm(pe.get_data(function,256),function):
        ins.append(dict(rva=hex(i.address),instruction=i.mnemonic+' '+i.op_str))
        if i.mnemonic=='ret':break
    assert ins[-1]['instruction'].startswith('ret')
    rows.append(dict(savedId=index,category=category,constructor=hex(ctor),constructorSource=str(files[0].relative_to(root)),
        derivedVtable=hex(vt),sizeSlot='0x48',sizeFunction=hex(function),instructions=ins,
        behaviour='Population' if index==1 else 'Commodity' if index==9 else 'Colonisation' if index==13 else 'Uniform'))
appearance=json.loads((root/'artifacts/galaxy-query-research/palette-resources/original-appearance.json').read_text())
frozen=(root/'artifacts/galaxy-query-research/palette-resources'/f"{appearance['sourceResource']}.indexed1").read_bytes()
assert hashlib.sha256(frozen).hexdigest()==appearance['frozenSha256']
offset=appearance['configuration']['fileOffset']
default=struct.unpack_from('<f',frozen,offset+0x1c)[0]
multiplier=struct.unpack_from('<f',frozen,offset+0x188)[0]
assert default==appearance['defaultSize'] and multiplier==struct.unpack('<f',bytes.fromhex('9a99193f'))[0]
asfile=root/'artifacts/galaxy-marker-research/map-as/scripts/components/leftHandPanels/GMSizeFilterComponent.as'
source=asfile.read_text(encoding='utf8')
assert 'CheckboxButton id="sizeFilterOptionsComboBox"' in source and 'label="$GALAXY_MAP_FILTER_population;"' in source
assert '"optionToggled"' in source and '"sliderData"' in source
assert source.count('<CheckboxButton ')==1
result=dict(imageSha256=digest,gameProcessAccess=False,gameCalls=0,networkRequests=0,
    currentPanel=dict(source=str(asfile.relative_to(root)),sha256=hashlib.sha256(asfile.read_bytes()).hexdigest(),
        offeredCategories=['None','Population'],control='one population CheckboxButton, despite its ComboBox member name'),
    savedSizeChannels=rows,constants=dict(resourceSha256=appearance['sourceSha256'],frozenSha256=appearance['frozenSha256'],
        configurationFileOffset=offset,defaultField='0x1c',defaultSize=default,colonisationMultiplierField='0x188',colonisationMultiplier=multiplier),
    colonisation=dict(classifier='0x3b1a200',classifierSource='account-sources/decompiled/solo-3b1a200.c',
        rawStatusesForClassification1=[5,6],formula='defaultSize * (classification==1 ? config188 : 1)'),
    boundary='Saved compatibility is not proof that all saved IDs appear in the current UI. 3A9F320/3B17400 are Colonisation builders, not size-menu evidence.')
out=root/'artifacts/galaxy-query-research/size-options/original-size-options.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.relative_to(root)),savedChannels=len(rows),currentPanel=result['currentPanel']['offeredCategories'],colonisationMultiplier=multiplier)))