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

XFEEDToolBox

【WinUI】XFE精英危险工具箱

公开
关注 0 Fork 0 Star 0
UTF-8
"""Pinned offline frame bindings/constants and relocatable pure alpha consumer.

No game process is opened. The optional research probe executes only the
guarded, call-free original arithmetic function inside its own process.
"""
from pathlib import Path
import hashlib, json, struct
import pefile
from capstone import Cs, CS_ARCH_X86, CS_MODE_64, CS_OP_MEM, CS_OP_IMM

IMAGE=Path('artifacts/ship-model-reference/client-copy/EliteDangerous64.exe')
OUT=Path('artifacts/galaxy-query-research/power-outer-sources/frame-fade')
raw=IMAGE.read_bytes()
image_sha=hashlib.sha256(raw).hexdigest()
assert image_sha=='6891f70a021fa9f3a0e00458c284f48d1226e68ae7fc02ad48081aed47857e93'
pe=pefile.PE(data=raw,fast_load=True)
pe.parse_data_directories(directories=[pefile.DIRECTORY_ENTRY['IMAGE_DIRECTORY_ENTRY_EXCEPTION']])
spans={entry.struct.BeginAddress:entry.struct.EndAddress for entry in pe.DIRECTORY_ENTRY_EXCEPTION}
dis=Cs(CS_ARCH_X86,CS_MODE_64);dis.detail=True
def value(rva):return struct.unpack('<f',pe.get_data(rva,4))[0]
def guard(rva,expected):assert pe.get_data(rva,len(bytes.fromhex(expected)))==bytes.fromhex(expected),hex(rva)

# Actual native Camera is embedded at frame20; its frustum goes to exactly
# the frame600 layout subsequently copied by the Galaxy renderer3A653E0.
guard(0x5A8D03,'4883c120e8c4abf4ff')
guard(0x5A8DE0,'0f118600060000')
guard(0x5A8E09,'898640060000')
guard(0x2874449,'0f116720') # Native Camera+20 = normalized source forward.
guard(0x28744AD,'0f114730') # Native Camera+30 = pose translation/eye.
constants={name:dict(rva=hex(rva),raw=pe.get_data(rva,4).hex(),value=value(rva)) for name,rva in
    [('nearEnd',0x50CB470),('nearStartDivisor',0x4E328D0),('farStart',0x515D570),('farEnd',0x515D510),
     ('radiusThird',0x50CB434),('radiusOuterAddition',0x4E29758),('minimumFloorGate',0x5324D60),
     ('transitionUpperLimit',0x4DEDFD4),('transitionRate',0x4DEAA5C)]]
assert [constants[n]['value'] for n in ['nearEnd','nearStartDivisor','farStart','farEnd']]==[3.,2.,600.,700.]
near_start=constants['nearEnd']['value']/constants['nearStartDivisor']['value']
assert near_start==1.5

functions=[]
for rva,folder in [(0x5A8CD0,'frame-fade'),(0x2874350,'../../constellations/decompiled'),
    (0x3A26260,'decompiled'),(0x3ACA010,'decompiled'),(0x3AFBD80,'decompiled'),(0x3A27E60,'decompiled')]:
    end=spans[rva];code=pe.get_data(rva,end-rva)
    path=OUT.parent/folder/f'solo-{rva:x}.c'
    functions.append(dict(rva=hex(rva),bytes=len(code),codeSha256=hashlib.sha256(code).hexdigest(),
        decompilation=str(path),decompilationSha256=hashlib.sha256(path.read_bytes()).hexdigest()))

# Relocate only RIP-relative, read-only constants. Direct conditional branches
# remain inside the copied function. No calls, indirect control transfers,
# system instructions, or writes outside the explicit output pointer exist.
start=0x3AFBD80;original=pe.get_data(start,spans[start]-start)
instructions=list(dis.disasm(original,start))
assert sum(i.size for i in instructions)==len(original)
assert not any(i.mnemonic.startswith(('call','sys','int')) for i in instructions)
for i in instructions:
    if i.group(1): # CS_GRP_JUMP
        assert i.operands[0].type==CS_OP_IMM and start<=i.operands[0].imm<start+len(original)
payload=bytearray(original);relocations=[];locations={}
for i in instructions:
    for operand in i.operands:
        if operand.type!=CS_OP_MEM:continue
        mem=operand.mem
        if dis.reg_name(mem.base)=='rip':
            target=i.address+i.size+mem.disp
            section=next(s for s in pe.sections if s.VirtualAddress<=target<s.VirtualAddress+max(s.Misc_VirtualSize,s.SizeOfRawData))
            assert not section.Characteristics&0x80000000 and not section.Characteristics&0x20000000
            if target not in locations:
                at=(len(payload)+15)&~15;payload.extend(b'\0'*(at-len(payload)))
                locations[target]=at;payload.extend(pe.get_data(target,16))
            at=locations[target];instruction_offset=i.address-start
            assert i.disp_size==4
            struct.pack_into('<i',payload,instruction_offset+i.disp_offset,at-(instruction_offset+i.size))
            relocations.append(dict(instruction=hex(i.address),target=hex(target),localOffset=at))
        elif operand.access&2:
            assert dis.reg_name(mem.base)=='rdx' and mem.disp==0 and mem.index==0
path=OUT/'original-alpha-consumer.bin';path.write_bytes(payload)
result=dict(imageSha256=image_sha,gameProcessAccess=False,gameCalls=0,
    frameBinding=dict(nativeCameraOffset='0x20',forward='frame40 = nativeCamera20',eye='frame50 = nativeCamera30',
        proof='5A8CD0 calls4F38D0(frame20) and copies its original frustum toframe600/610/620/count640/644/646',
        cameraPoseWriter='2874350 stores normalized source Z atCamera20 and source translation atCamera30'),
    builder=dict(rva='0x3ACA010',caller='0x3A26260',offset=[0,0,0],planeOrigin='frame50/Eye',
        planeScale='frame40/Forward',ellipsoidOrigin='orbit5F05DCC+48/Focus',radius='renderer280',
        transition='input5FDB21C+58 ->component1A8 current smoothed float',nearStart=near_start,
        nearEnd=3.,farStart=600.,farEnd=700.),constants=constants,functions=functions,
    ordinaryRadius='3B46FD0 ->rendererinterface+20/3AB5A60 writes interface228 = component280: baseRadius*DD4Modifier*runtimeMultiplier; NOT sparseExpansionOuterRadius',
    territoryConsumer=dict(rva='0x3A27E60',recordBytes=32,sourceAlphaMultiplied=True,bypassMinimum=True,farFade=True),
    outerBoundary='Do not apply Territory flags to all outer64B geometry; its own consumers and mode alpha remain separate.',
    alphaConsumer=dict(rva=hex(start),originalBytes=len(original),originalSha256=hashlib.sha256(original).hexdigest(),
        relocatablePath=str(path),payloadBytes=len(payload),payloadSha256=hashlib.sha256(payload).hexdigest(),
        originalCallCount=0,relocations=relocations,ownProcessProbeOnly=True),
    unclosed=['current runtime renderer280 and Settings threshold/mode snapshots',
        'actual smoothed input1A8 without initialization/step history',
        'live current-version frame and per-consumer outer rendering'],productionFrameFadeEnabled=False)
(OUT/'original-frame-fade.json').write_text(json.dumps(result,indent=2)+'\n',encoding='utf-8')
print(json.dumps(dict(nearStart=near_start,sourceFunctions=len(functions),consumerBytes=len(original),
    relocations=len(relocations),output=str(OUT/'original-frame-fade.json'))))