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

XFEEDToolBox

【WinUI】XFE精英危险工具箱

公开
关注 0 Fork 0 Star 0
UTF-8
"""Bind original material wrapper offsets to actual property names, offline."""
from pathlib import Path
import hashlib,json,re,struct
import pefile
from capstone import Cs,CS_ARCH_X86,CS_MODE_64
from capstone.x86_const import X86_OP_IMM,X86_OP_MEM,X86_REG_RIP

image=Path('artifacts/ship-model-reference/client-copy/EliteDangerous64.exe').read_bytes()
image_sha=hashlib.sha256(image).hexdigest()
if image_sha!='6891f70a021fa9f3a0e00458c284f48d1226e68ae7fc02ad48081aed47857e93':
    raise ValueError('Pinned image changed')
pe=pefile.PE(data=image,fast_load=True)
base=pe.OPTIONAL_HEADER.ImageBase
pe.parse_data_directories(directories=[pefile.DIRECTORY_ENTRY['IMAGE_DIRECTORY_ENTRY_EXCEPTION']])
entry=next(e.struct for e in pe.DIRECTORY_ENTRY_EXCEPTION if e.struct.BeginAddress==0x3A09F20)
code=pe.get_data(entry.BeginAddress,entry.EndAddress-entry.BeginAddress)
decoder=Cs(CS_ARCH_X86,CS_MODE_64);decoder.detail=True
instructions=list(decoder.disasm(code,base+entry.BeginAddress))
folder=Path('artifacts/galaxy-query-research/power-outer-sources/material-slots')
ctor=Path('artifacts/galaxy-query-research/constellations/decompiled/solo-3a09f20.c')
source=ctor.read_text()
pattern=r'func_0x000140535ff0\([^;]*&UNK_([0-9a-f]+)\);.*?FUN_144348480\(param_1 \+ (0x[0-9a-f]+|[0-9]+),uVar6\);\s*\*\(undefined4 \*\)\(param_1 \+ (0x[0-9a-f]+|[0-9]+)\) = (0x[0-9a-f]+);'
rows=[]
for match in re.finditer(pattern,source,re.S):
    name_va=int(match[1],16)
    raw=pe.get_data(name_va-base,256)
    name=raw.split(b'\0',1)[0].decode('ascii')
    if not name or not all(32<=ord(c)<127 for c in name):raise ValueError('Invalid source property string')
    wrapper=int(match[2],0)*8
    value=int(match[3],0)*8
    if value-wrapper!=0x88:raise ValueError('Original scalar wrapper layout changed')
    bits=int(match[4],16)
    name_loads=[i for i in instructions if any(o.type==X86_OP_MEM and o.mem.base==X86_REG_RIP
        and i.address+i.size+o.mem.disp==name_va for o in i.operands)]
    value_stores=[i for i in instructions if i.mnemonic=='mov' and len(i.operands)==2
        and i.operands[0].type==X86_OP_MEM and i.operands[0].mem.disp==value
        and i.operands[0].size==4 and i.operands[1].type==X86_OP_IMM and i.operands[1].imm&0xffffffff==bits]
    if len(name_loads)!=1 or len(value_stores)!=1:raise ValueError('Constructor does not bind the claimed name/default member')
    rows.append(dict(wrapperOffset=hex(wrapper),valueOffset=hex(value),nameRva=hex(name_va-base),
        name=name,defaultBits=hex(bits),defaultFloat=struct.unpack('<f',struct.pack('<I',bits))[0],
        nameLoadRva=hex(name_loads[0].address-base),nameLoadBytes=name_loads[0].bytes.hex(),
        defaultStoreRva=hex(value_stores[0].address-base),defaultStoreBytes=value_stores[0].bytes.hex()))
if [r['valueOffset'] for r in rows[:4]]!=['0x98','0x128','0x1b8','0x248']:
    raise ValueError('Original runtime four scalar slots not recovered')
scope={}
exec(Path('research/Extract-OriginalGalaxyAppearance.py').read_text().split('tables={}')[0],scope)
frozen=scope['b']
if hashlib.sha256(frozen).hexdigest()!='5135b3d55e5239b3d11f79a76adeda954eb78be5101b6a516fd25df257affa77':
    raise ValueError('Original renderer configuration changed')
config=(295,14000)
vectors={hex(field):scope['floats'](scope['references'][(config[0],config[1]+field)],count)
    for field,count in ((0x90,4),(0x98,4),(0x180,3),(0x188,3))}
if pe.get_data(0x3ACBC7E,7)!=bytes.fromhex('c686d802000000'):
    raise ValueError('Original alternate-glow default changed')
if int.from_bytes(pe.get_data(0x552D5F0+0x90,8),'little')-base!=0x3B442E0 or pe.get_data(0x3B442E0,8)!=bytes.fromhex('0fb68180020000c3'):
    raise ValueError('Original alternate-glow getter changed')
result=dict(gameProcessAccess=False,gameCalls=0,imageSha256=image_sha,constructorRva='0x3A09F20',
    constructorBytes=len(code),constructorCodeSha256=hashlib.sha256(code).hexdigest(),
    constructorDecompilerSha256=hashlib.sha256(ctor.read_bytes()).hexdigest(),properties=rows,
    runtimeWriteRva='0x3AB44E0',runtimeConfigField='0x90',runtimeSlots=rows[:4],
    configurationFrozenSha256=hashlib.sha256(frozen).hexdigest(),runtimeVectors=vectors,
    stellarInternalGlow=dict(names=['pInternalGlowParamsX','pInternalGlowParamsY','pInternalGlowParamsZ'],
        valueOffsets=['0x998','0xA28','0xAB8'],defaultSource='0x180',alternateSource='0x188',
        alternateFlag=dict(mainField='0x2D8',getterRva='0x3B442E0',getterInterfaceField='0x280',
            initialValue=0,initializerRva='0x3ACBC7E',semanticNameUnknown=True)),
    note='Named material properties, not compiled CB2 scalar order. Shader reflection binding remains separate.')
folder.mkdir(exist_ok=True)
(folder/'material-property-slots.json').write_text(json.dumps(result,indent=2)+'\n')
print(json.dumps(dict(properties=len(rows),runtimeSlots=result['runtimeSlots']),indent=2))