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

XFEEDToolBox

【WinUI】XFE精英危险工具箱

公开
关注 0 Fork 0 Star 0
UTF-8
"""Pinned normal frame-clock source, clamps, dispatch and ordinary-star flags.

Only reads the immutable old client; never opens a game process or executes
its functions. Current-client native addresses are outside this script.
"""
from pathlib import Path
import hashlib
import json
import struct
import pefile
from capstone import Cs, CS_ARCH_X86, CS_MODE_64

ROOT = Path(__file__).resolve().parents[1]
OUT = ROOT / 'artifacts/galaxy-query-research/power-outer-sources/frame-fade-state'
raw = (ROOT / 'artifacts/ship-model-reference/client-copy/EliteDangerous64.exe').read_bytes()
sha = hashlib.sha256(raw).hexdigest()
assert sha == '6891f70a021fa9f3a0e00458c284f48d1226e68ae7fc02ad48081aed47857e93'
pe = pefile.PE(data=raw, fast_load=True)
pe.parse_data_directories(directories=[pefile.DIRECTORY_ENTRY['IMAGE_DIRECTORY_ENTRY_IMPORT']])
base = pe.OPTIONAL_HEADER.ImageBase
dis = Cs(CS_ARCH_X86, CS_MODE_64)
proof = []


def instruction(rva, expected):
    ins = next(dis.disasm(pe.get_data(rva, 15), rva))
    actual = ins.mnemonic+' '+ins.op_str
    assert actual == expected, (hex(rva), actual, expected)
    proof.append(dict(rva=hex(rva), bytes=ins.bytes.hex(), instruction=actual))


def pointer(rva, target):
    assert struct.unpack('<Q', pe.get_data(rva, 8))[0] == base+target
    proof.append(dict(rva=hex(rva), pointerRva=hex(target)))


def constant(rva, expected):
    value = struct.unpack('<f', pe.get_data(rva, 4))[0]
    assert value == expected, (hex(rva), value)
    proof.append(dict(rva=hex(rva), bytes=pe.get_data(rva, 4).hex(), float=value))
    return value


minimum = constant(0x4DEE008, 9.999999747378752e-06)
normal_maximum = constant(0x4DE28B8, .5)
long_threshold = constant(0x4DED004, 4)
long_value = constant(0x511D364, .03333333507180214)
constant(0x4E3410C, 1000000000)
iat = 0x54D7EE+6+struct.unpack('<i', pe.get_data(0x54D7EE+2, 4))[0]
imports = [(mod.dll.decode(), entry.name.decode()) for mod in pe.DIRECTORY_ENTRY_IMPORT
    for entry in mod.imports if entry.address-base == iat]
assert imports == [('KERNEL32.dll', 'GetSystemTimeAsFileTime')]
proof.append(dict(rva=hex(iat), importName=imports[0][1]))

# Default wall clock -> normalized seconds/nanoseconds difference -> float seconds.
instruction(0x7F96E1, 'xor edx, edx')
instruction(0x7F96E8, 'call 0x54d7d0')
instruction(0x7F96ED, 'cmp byte ptr [rsi + 0x9b4], r14b')
instruction(0x7F96F9, 'divss xmm6, dword ptr [rsi + 0x9b0]')
instruction(0x7F9713, 'call 0x53e6e0')
instruction(0x7F971B, 'call 0x52c3f0')
instruction(0x7F972F, 'call 0x53b6a0')
instruction(0x7F973A, 'call 0x7f3430')
instruction(0x53E6FA, 'sub rax, qword ptr [r8]')
instruction(0x53E700, 'sub r9d, dword ptr [r8 + 8]')
instruction(0x52C3F8, 'cvtsi2ss xmm1, qword ptr [rcx]')
instruction(0x52C400, 'divss xmm0, dword ptr [rip + 0x4907d04]')
instruction(0x52C408, 'addss xmm0, xmm1')

# The original clamp is intentionally discontinuous at raw=4 seconds.
instruction(0x7F3459, 'maxss xmm7, xmm1')
instruction(0x7F347B, 'comiss xmm7, dword ptr [rip + 0x45f9b82]')
instruction(0x7F3482, 'jbe 0x7f3503')
instruction(0x7F350F, 'minss xmm6, xmm7')
pointer(0x4DDF490+0xD0, 0x1EB9C0)
pointer(0x4DDF490+0xC8, 0x1EB050)
instruction(0x7F35D6, 'movaps xmm1, xmm6')
instruction(0x7F35DC, 'call qword ptr [rdx + 0xd0]')
instruction(0x7F39BC, 'call qword ptr [rax + 0xc8]')
instruction(0x1EB9F3, 'movaps xmm6, xmm1')
instruction(0x1EBA0B, 'movss dword ptr [rcx + 0x8494], xmm6')
instruction(0x1EB225, 'movss xmm6, dword ptr [rbx + 0x8494]')
instruction(0x1EB23D, 'lea rax, [rip + 0x4bf5d54]')
instruction(0x1EB244, 'movss dword ptr [rbp + 0x20], xmm6')
instruction(0x1EB255, 'lea rcx, [rip + 0x5d15544]')
instruction(0x1EB260, 'call 0x7eb700')

# 5F007A0 is the publisher. 5FDB7D0 is a type/dependency key, whose
# adjacent callback table selects the input thunk; it is not the publisher.
pointer(0x4DE0F98+8, 0x1EC720)
pointer(0x5529D98, 0x3ABA020)
instruction(0x7EB782, 'mov rdx, qword ptr [rbx + 8]')
instruction(0x7EB79A, 'call qword ptr [rax + 8]')
instruction(0x1EC748, 'movss xmm0, dword ptr [rax]')
instruction(0x1EC759, 'lea rdi, [rax - 8]')
instruction(0x1EC82C, 'call 0x1e7040')
instruction(0x1E7091, 'mov rax, qword ptr [rcx]')
instruction(0x1E7094, 'mov r8, qword ptr [rax]')
instruction(0x1E709B, 'movss xmm2, dword ptr [rax]')
instruction(0x1E709F, 'call r8')
instruction(0x3ABA029, 'movaps xmm1, xmm2')
instruction(0x3ABA030, 'jmp 0x3af5d70')
# Parallel dispatch wrapper uses the same float-preserving worker.
instruction(0x1EEED0, 'mov rcx, qword ptr [rcx + 8]')
instruction(0x1EEED4, 'jmp 0x1e7040')

# Star style writer's actual default and override switches.
instruction(0x3A15ED2, 'movzx r13d, r15b')
instruction(0x3A15F64, 'xor bpl, bpl')
instruction(0x3A15F69, 'movzx ebp, r13b')
instruction(0x3A15F6F, 'movzx r13d, byte ptr [rbx + 8]')
instruction(0x3A15F74, 'xor bpl, bpl')
instruction(0x3A1608D, 'movzx r9d, bpl')
instruction(0x3A16091, 'mov byte ptr [rsp + 0x20], r13b')
instruction(0x3A1609B, 'call 0x3afbd80')
instruction(0x3A160AB, 'mulss xmm0, dword ptr [r14]')
instruction(0x3A160F3, 'mulss xmm0, xmm1')
instruction(0x3A1614D, 'movups xmm0, xmmword ptr [rsp + 0x60]')
instruction(0x3A16158, 'movups xmmword ptr [rbx + 0x14], xmm0')

result = dict(imageSha256=sha, gameProcessAccess=False, gameCalls=0,
    elapsedSecondsProved=True,
    ordinaryClock=dict(source='7F8CC0 ->54D7D0(GetSystemTimeAsFileTime, selector0)',
        delta='53E6E0(now,previousApp3F8) subtracts seconds64/nanoseconds32;53B6A0 publishes new previous timestamp',
        units='52C3F0: float(seconds64)+float(nanoseconds32)/float(1e9)',
        fixedStep='Only if app9B4 is set:1.0f/app9B0; explicit fixedFramesPerSecond in tool API',
        alternativeProvider='Startup branch can use optional app568 provider; ordinary loop resets that provider before normal timestamp loop'),
    policy=dict(minimum=minimum, normalMaximum=normal_maximum, longFrameThreshold=long_threshold,
        longFrameMaximum=long_value, longFrameComparison='strictly greater than4 after float conversion and minimum',
        formula='raw=max(minimum,elapsedSeconds); frame=min(raw,raw>4?1/30:.5)'),
    dispatch=dict(source='7F3430 actualApp virtualD0 ->1EB9C0 stores8494; then actualApp virtualC8 ->1EB050',
        publisher='1EB050 passes8494 unchanged to global5F007A0 via descriptor4DE0F98',
        timing='This publication precedes5F052C0 and input5F05BC0 virtual18 within1EB050',
        key='Activation810FA0/12D1BA0 uses7E9B00(5F007A0,handleScope,5FDB7D0)',
        forwarding='7EB700 ->descriptor1EC720 ->1E7040 ->5529D98[0]/3ABA020 ->3AF5D70; no float arithmetic after8494',
        parallel='4DE1378+8/1EEED0 also jumps to1E7040'),
    ordinaryStars=dict(consumer='3A15D90/3A1609B', bypassMinimum=True, farFade=True,
        conditions='No D50 cache entry and optional5F05DD0 interface110 does not select the special branch',
        cacheOverride='bypassMinimum=0;farFade=cacheEntry8', specialOverride='bypassMinimum=0;farFade=1',
        multiplication='frameAlpha*existingOpacity, then appearanceRGBA.alpha*=resultingOpacity',
        sizeMultiplied=False, sizeProof='appearance size atstack60 is copied unmodified to style14; alpha is stack70',
        furtherOpacity='Appearance interface90 can independently multiply resulting opacity by.5'),
    productionApi='GalaxyOriginalFrameFadeClock.TryFromElapsedSeconds(elapsedSeconds,out frameValue,fixedFramesPerSecond:null)',
    currentVersionLiveAccepted=False, proofs=proof)
OUT.mkdir(parents=True, exist_ok=True)
path = OUT / 'original-frame-clock.json'
path.write_text(json.dumps(result, indent=2)+'\n', encoding='utf-8')
print(json.dumps(dict(proofCount=len(proof), elapsedSecondsProved=True, ordinaryStarFlags=[1,1],
    sizeMultiplied=False, output=str(path))))