"""Bounded paired-file exposure proof; no runtime access or loadable address profile."""
from pathlib import Path
import hashlib,importlib.util,json,struct,zlib
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'))
expected=('6891f70a021fa9f3a0e00458c284f48d1226e68ae7fc02ad48081aed47857e93',
'ed5a8f8cd10f9a80d3bda5badd7ba1d4fcfc15996c8c7e018852cb170e264b63')
actual=tuple(hashlib.sha256(i.raw).hexdigest() for i in (old,new))
if actual!=expected:raise ValueError('The exact two exposure images changed: '+repr(actual))
functions=[];references=[];mapping={};unknown=[]
for before in [0x351F8E0,0x351F450,0x3526320,0x3523480,0x3525E70,0x3521E90]:
span=old.function(before)
if not span or span[0]!=before:raise ValueError('Unproved original function entry '+hex(before))
length=span[1]-before;row=audit.match(old,new,before,length);row['oldRva']=hex(before)
if row['status']!='unique':
unknown.append(dict(oldRva=hex(before),reason='Full function is not a unique match',match=row));functions.append(row);continue
after=int(row['newRva'],16);target=new.function(after)
raw,mask,*_=audit.signature(old,before,length)
if len(raw)!=length or not target or target[0]!=after or target[1]-after!=length:
unknown.append(dict(oldRva=hex(before),newRva=hex(after),reason='Full unwind span or disassembly coverage differs',
originalBytes=length,matchedBytes=len(raw),newRange=target));functions.append(row);continue
other=new.data(after,length)
if any(a!=b for a,b,keep in zip(raw,other,mask) if keep):raise ValueError('Unexplained instruction byte difference')
refs=audit.references(old,new,before,after,length)
if not refs:raise ValueError('No paired reference evidence for a large exposure function')
references.extend(refs);mapping[before]=after
row.update(fullFunctionBytes=length,fullUnwindSpanMatched=True,normalizedIdentical=True,
oldInstructions=len(old.instructions(before,length)),newInstructions=len(new.instructions(after,length)))
functions.append(row)
def paired_global(before,size):
targets={r[1] for r in references if r[0]==before}
if len(targets)!=1:return None
after=targets.pop();left=old.data(before,size);right=new.data(after,size)
return dict(oldRva=hex(before),newRva=hex(after),oldSection=old.section(before),newSection=new.section(after),
oldRaw=left.hex(),newRaw=right.hex(),initialBytesEqual=left==right,
referencedBy=[dict(oldFunction=hex(r[2]),oldInstruction=hex(r[3]),
newInstruction=hex(mapping[r[2]]+r[3]-r[2]))for r in references if r[0]==before])
controls=[]
for name,before,bits in [('ToeModifier',0x5E8B918,'d7a3803f'),('ShoulderModifier',0x5E8B910,'33331340'),
('Offset',0x5E8B908,'0000a040'),('Slope',0x5E8B914,'0000803f')]:
row=paired_global(before,4)
if row is None:unknown.append(dict(name=name,oldRva=hex(before),reason='Missing/ambiguous actual RIP reference'));continue
row['name']=name;row['initialFloat']=struct.unpack('<f',bytes.fromhex(row['newRaw']))[0]
if row['oldRaw']!=bits or row['oldSection']!='.data' or row['newSection']!='.data' or not row['initialBytesEqual']:
unknown.append(dict(name=name,reason='Initial global bits or data section changed',evidence=row))
controls.append(row)
flags=[]
for name,before in [('CurveOverrideEnabled',0x5E8B997),('ExposureDispatchEnabled',0x5E8B994)]:
row=paired_global(before,1)
if row is None:unknown.append(dict(name=name,oldRva=hex(before),reason='Missing/ambiguous actual RIP reference'));continue
row['name']=name
if row['oldRaw']!='01' or row['oldSection']!='.data' or row['newSection']!='.data' or not row['initialBytesEqual']:
unknown.append(dict(name=name,reason='Initial flag or data section changed',evidence=row))
flags.append(row)
def instruction_block(function,first,last):
if function not in mapping:return None
after=mapping[function];rows=[]
a=old.instructions(first,last-first+15)
for i in a:
rva=i.address-old.base
if rva>last:break
target=after+rva-function
j=new.instructions(target,i.size)[0]
if i.mnemonic!=j.mnemonic or i.size!=j.size:raise ValueError('Changed exposure anchor shape')
rows.append(dict(oldRva=hex(rva),newRva=hex(target),oldRaw=i.bytes.hex(),newRaw=j.bytes.hex(),
oldInstruction=i.mnemonic+' '+i.op_str,newInstruction=j.mnemonic+' '+j.op_str))
return rows
stores=[]
for anchor,raw in [(0x351FA75,'48c786fc0000000000003f'),(0x351FA95,'48c7861c0100000000803f')]:
rows=instruction_block(0x351F8E0,anchor,anchor)
if rows:
if rows[0]['oldRaw']!=raw or rows[0]['newRaw']!=raw:raise ValueError('Exposure default 64bit store changed')
stores.extend(rows)
copy_ev=instruction_block(0x3526320,0x35263B4,0x35263C2)
copy_mode=instruction_block(0x3526320,0x3526436,0x3526444)
selection=instruction_block(0x3523480,0x3525DC4,0x3525DDB)
if selection:
before=[r['oldInstruction']for r in selection][-5:];after=[r['newInstruction']for r in selection][-5:]
if before[:4]!=['mov rdx, r12','sete sil','xor r9d, r9d','mov r8d, esi'] or after[:4]!=before[:4]:
raise ValueError('mode0 -> manual pass index selection changed')
program=None
source=0x54C4568
program_targets={r[1]for r in references if r[0]==source}
descriptor=0x54C6248;descriptor_evidence=[]
for target_descriptor in {r[1]for r in references if r[0]==descriptor}:
old_platform,old_payload=struct.unpack('<2Q',old.data(descriptor,16))
new_platform,new_payload=struct.unpack('<2Q',new.data(target_descriptor,16))
if old_payload-old.base!=source or old.data(old_platform-old.base,11)!=b'Win64_SM50\0' or new.data(new_platform-new.base,11)!=b'Win64_SM50\0':
raise ValueError('Actual3521E90 embedded compute descriptor changed platform/source')
program_targets.add(new_payload-new.base)
descriptor_evidence.append(dict(oldRva=hex(descriptor),newRva=hex(target_descriptor),oldRaw=old.data(descriptor,16).hex(),newRaw=new.data(target_descriptor,16).hex(),
oldPayload=hex(source),newPayload=hex(new_payload-new.base),oldPlatform=hex(old_platform-old.base),newPlatform=hex(new_platform-new.base),platform='Win64_SM50',
references=[list(map(hex,r))for r in references if r[0]==descriptor]))
if len(program_targets)==1:
target=program_targets.pop();payloads=[zlib.decompress(i.data(rva+16,7370),-15)for i,rva in [(old,source),(new,target)]]
sha=[hashlib.sha256(p).hexdigest()for p in payloads]
if sha!=['62ef0e8e73e653df972031438fdf5a44e5c152e3c7aa0c9af8fd42e14df7cea7']*2:
unknown.append(dict(reason='Embedded exposure program changed',oldRva=hex(source),newRva=hex(target),sha256=sha))
else:
p=payloads[1];cursor=p.index(b'\x08\x02xfxd3f')+8;marker=p.index(b'\0\1voMrtP',cursor)
length,count=struct.unpack_from('<2I',p,marker+8);first=p[marker+16:marker+16+length]
ptr,n=struct.unpack_from('<2Q',first,8);passes=[]
for index in range(n):
name=struct.unpack_from('<Q',first,ptr+index*0x70)[0];passes.append(first[name:first.index(b'\0',name)].decode('ascii'))
if passes!=['AnalyseLuminance_AutoExposure','AnalyseLuminance_ManualExposure']:raise ValueError('Actual ordered exposure passes changed')
program=dict(oldRva=hex(source),newRva=hex(target),compressedBytes=7370,sha256=sha[0],identical=True,passes=passes,pairedDescriptor=descriptor_evidence,
directReferences=[list(map(hex,r))for r in references if r[0]==source])
else:unknown.append(dict(reason='Embedded exposure program has no unique actual paired source reference',oldRva=hex(source),targets=list(map(hex,program_targets))))
result=dict(scope='Bounded static ED5 exposure default compatibility; never runtime producer readiness',
oldImage=dict(path=str(old.path),sha256=actual[0]),newImage=dict(path=str(new.path),sha256=actual[1]),
gameProcessAccess=False,gameCalls=0,networkRequests=0,productionModified=False,runtimeValidated=False,canInstallHooks=False,
functions=functions,references=[list(map(hex,r))for r in references],controls=controls,flags=flags,
ownerDefaults=dict(ev=0,mode=0,paired64BitStores=stores),perRenderCopy=dict(ev=copy_ev,mode=copy_mode),
mode0SelectsManual=bool(selection and program),manualSelection=selection,compiledProgram=program,
unknown=unknown,allBoundedChecksClosed=not unknown,
limits=['Initial data/constructor stores do not assert current game values or a completed compute dispatch.',
'The paired exposure mode is a static default for an explicit tool-owned ManualCS fallback, never another camera histogram.'])
out=Path('artifacts/galaxy-client-compatibility/exposure-controls-paired.json');out.parent.mkdir(parents=True,exist_ok=True)
out.write_text(json.dumps(result,indent=2)+'\n')
print(json.dumps(dict(path=str(out),closed=result['allBoundedChecksClosed'],functions=[dict(old=f['oldRva'],new=f.get('newRva'),status=f['status'],bytes=f.get('fullFunctionBytes'))for f in functions],controls=controls,flags=flags,mode0SelectsManual=result['mode0SelectsManual'],unknown=unknown),indent=2))
"""Bounded paired-file exposure proof; no runtime access or loadable address profile."""
from pathlib import Path
import hashlib,importlib.util,json,struct,zlib
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'))
expected=('6891f70a021fa9f3a0e00458c284f48d1226e68ae7fc02ad48081aed47857e93',
'ed5a8f8cd10f9a80d3bda5badd7ba1d4fcfc15996c8c7e018852cb170e264b63')
actual=tuple(hashlib.sha256(i.raw).hexdigest() for i in (old,new))
if actual!=expected:raise ValueError('The exact two exposure images changed: '+repr(actual))
functions=[];references=[];mapping={};unknown=[]
for before in [0x351F8E0,0x351F450,0x3526320,0x3523480,0x3525E70,0x3521E90]:
span=old.function(before)
if not span or span[0]!=before:raise ValueError('Unproved original function entry '+hex(before))
length=span[1]-before;row=audit.match(old,new,before,length);row['oldRva']=hex(before)
if row['status']!='unique':
unknown.append(dict(oldRva=hex(before),reason='Full function is not a unique match',match=row));functions.append(row);continue
after=int(row['newRva'],16);target=new.function(after)
raw,mask,*_=audit.signature(old,before,length)
if len(raw)!=length or not target or target[0]!=after or target[1]-after!=length:
unknown.append(dict(oldRva=hex(before),newRva=hex(after),reason='Full unwind span or disassembly coverage differs',
originalBytes=length,matchedBytes=len(raw),newRange=target));functions.append(row);continue
other=new.data(after,length)
if any(a!=b for a,b,keep in zip(raw,other,mask) if keep):raise ValueError('Unexplained instruction byte difference')
refs=audit.references(old,new,before,after,length)
if not refs:raise ValueError('No paired reference evidence for a large exposure function')
references.extend(refs);mapping[before]=after
row.update(fullFunctionBytes=length,fullUnwindSpanMatched=True,normalizedIdentical=True,
oldInstructions=len(old.instructions(before,length)),newInstructions=len(new.instructions(after,length)))
functions.append(row)
def paired_global(before,size):
targets={r[1] for r in references if r[0]==before}
if len(targets)!=1:return None
after=targets.pop();left=old.data(before,size);right=new.data(after,size)
return dict(oldRva=hex(before),newRva=hex(after),oldSection=old.section(before),newSection=new.section(after),
oldRaw=left.hex(),newRaw=right.hex(),initialBytesEqual=left==right,
referencedBy=[dict(oldFunction=hex(r[2]),oldInstruction=hex(r[3]),
newInstruction=hex(mapping[r[2]]+r[3]-r[2]))for r in references if r[0]==before])
controls=[]
for name,before,bits in [('ToeModifier',0x5E8B918,'d7a3803f'),('ShoulderModifier',0x5E8B910,'33331340'),
('Offset',0x5E8B908,'0000a040'),('Slope',0x5E8B914,'0000803f')]:
row=paired_global(before,4)
if row is None:unknown.append(dict(name=name,oldRva=hex(before),reason='Missing/ambiguous actual RIP reference'));continue
row['name']=name;row['initialFloat']=struct.unpack('<f',bytes.fromhex(row['newRaw']))[0]
if row['oldRaw']!=bits or row['oldSection']!='.data' or row['newSection']!='.data' or not row['initialBytesEqual']:
unknown.append(dict(name=name,reason='Initial global bits or data section changed',evidence=row))
controls.append(row)
flags=[]
for name,before in [('CurveOverrideEnabled',0x5E8B997),('ExposureDispatchEnabled',0x5E8B994)]:
row=paired_global(before,1)
if row is None:unknown.append(dict(name=name,oldRva=hex(before),reason='Missing/ambiguous actual RIP reference'));continue
row['name']=name
if row['oldRaw']!='01' or row['oldSection']!='.data' or row['newSection']!='.data' or not row['initialBytesEqual']:
unknown.append(dict(name=name,reason='Initial flag or data section changed',evidence=row))
flags.append(row)
def instruction_block(function,first,last):
if function not in mapping:return None
after=mapping[function];rows=[]
a=old.instructions(first,last-first+15)
for i in a:
rva=i.address-old.base
if rva>last:break
target=after+rva-function
j=new.instructions(target,i.size)[0]
if i.mnemonic!=j.mnemonic or i.size!=j.size:raise ValueError('Changed exposure anchor shape')
rows.append(dict(oldRva=hex(rva),newRva=hex(target),oldRaw=i.bytes.hex(),newRaw=j.bytes.hex(),
oldInstruction=i.mnemonic+' '+i.op_str,newInstruction=j.mnemonic+' '+j.op_str))
return rows
stores=[]
for anchor,raw in [(0x351FA75,'48c786fc0000000000003f'),(0x351FA95,'48c7861c0100000000803f')]:
rows=instruction_block(0x351F8E0,anchor,anchor)
if rows:
if rows[0]['oldRaw']!=raw or rows[0]['newRaw']!=raw:raise ValueError('Exposure default 64bit store changed')
stores.extend(rows)
copy_ev=instruction_block(0x3526320,0x35263B4,0x35263C2)
copy_mode=instruction_block(0x3526320,0x3526436,0x3526444)
selection=instruction_block(0x3523480,0x3525DC4,0x3525DDB)
if selection:
before=[r['oldInstruction']for r in selection][-5:];after=[r['newInstruction']for r in selection][-5:]
if before[:4]!=['mov rdx, r12','sete sil','xor r9d, r9d','mov r8d, esi'] or after[:4]!=before[:4]:
raise ValueError('mode0 -> manual pass index selection changed')
program=None
source=0x54C4568
program_targets={r[1]for r in references if r[0]==source}
descriptor=0x54C6248;descriptor_evidence=[]
for target_descriptor in {r[1]for r in references if r[0]==descriptor}:
old_platform,old_payload=struct.unpack('<2Q',old.data(descriptor,16))
new_platform,new_payload=struct.unpack('<2Q',new.data(target_descriptor,16))
if old_payload-old.base!=source or old.data(old_platform-old.base,11)!=b'Win64_SM50\0' or new.data(new_platform-new.base,11)!=b'Win64_SM50\0':
raise ValueError('Actual3521E90 embedded compute descriptor changed platform/source')
program_targets.add(new_payload-new.base)
descriptor_evidence.append(dict(oldRva=hex(descriptor),newRva=hex(target_descriptor),oldRaw=old.data(descriptor,16).hex(),newRaw=new.data(target_descriptor,16).hex(),
oldPayload=hex(source),newPayload=hex(new_payload-new.base),oldPlatform=hex(old_platform-old.base),newPlatform=hex(new_platform-new.base),platform='Win64_SM50',
references=[list(map(hex,r))for r in references if r[0]==descriptor]))
if len(program_targets)==1:
target=program_targets.pop();payloads=[zlib.decompress(i.data(rva+16,7370),-15)for i,rva in [(old,source),(new,target)]]
sha=[hashlib.sha256(p).hexdigest()for p in payloads]
if sha!=['62ef0e8e73e653df972031438fdf5a44e5c152e3c7aa0c9af8fd42e14df7cea7']*2:
unknown.append(dict(reason='Embedded exposure program changed',oldRva=hex(source),newRva=hex(target),sha256=sha))
else:
p=payloads[1];cursor=p.index(b'\x08\x02xfxd3f')+8;marker=p.index(b'\0\1voMrtP',cursor)
length,count=struct.unpack_from('<2I',p,marker+8);first=p[marker+16:marker+16+length]
ptr,n=struct.unpack_from('<2Q',first,8);passes=[]
for index in range(n):
name=struct.unpack_from('<Q',first,ptr+index*0x70)[0];passes.append(first[name:first.index(b'\0',name)].decode('ascii'))
if passes!=['AnalyseLuminance_AutoExposure','AnalyseLuminance_ManualExposure']:raise ValueError('Actual ordered exposure passes changed')
program=dict(oldRva=hex(source),newRva=hex(target),compressedBytes=7370,sha256=sha[0],identical=True,passes=passes,pairedDescriptor=descriptor_evidence,
directReferences=[list(map(hex,r))for r in references if r[0]==source])
else:unknown.append(dict(reason='Embedded exposure program has no unique actual paired source reference',oldRva=hex(source),targets=list(map(hex,program_targets))))
result=dict(scope='Bounded static ED5 exposure default compatibility; never runtime producer readiness',
oldImage=dict(path=str(old.path),sha256=actual[0]),newImage=dict(path=str(new.path),sha256=actual[1]),
gameProcessAccess=False,gameCalls=0,networkRequests=0,productionModified=False,runtimeValidated=False,canInstallHooks=False,
functions=functions,references=[list(map(hex,r))for r in references],controls=controls,flags=flags,
ownerDefaults=dict(ev=0,mode=0,paired64BitStores=stores),perRenderCopy=dict(ev=copy_ev,mode=copy_mode),
mode0SelectsManual=bool(selection and program),manualSelection=selection,compiledProgram=program,
unknown=unknown,allBoundedChecksClosed=not unknown,
limits=['Initial data/constructor stores do not assert current game values or a completed compute dispatch.',
'The paired exposure mode is a static default for an explicit tool-owned ManualCS fallback, never another camera histogram.'])
out=Path('artifacts/galaxy-client-compatibility/exposure-controls-paired.json');out.parent.mkdir(parents=True,exist_ok=True)
out.write_text(json.dumps(result,indent=2)+'\n')
print(json.dumps(dict(path=str(out),closed=result['allBoundedChecksClosed'],functions=[dict(old=f['oldRva'],new=f.get('newRva'),status=f['status'],bytes=f.get('fullFunctionBytes'))for f in functions],controls=controls,flags=flags,mode0SelectsManual=result['mode0SelectsManual'],unknown=unknown),indent=2))