File size: 5,070 Bytes
31f9605
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
#!/usr/bin/env python3
"""Recover leader scan, cached location formatting and location-list registration."""
import json
import struct
from pathlib import Path
from analyze_deferred_auth import partition_function, trace_slice
from analyze_game_cvars import vm_string
from analyze_qvm import decode,write_json
from analyze_vm_extensions import verified


def main():
    q=json.loads(Path('docs/research/qvm/qagame.json').read_text())
    d=verified(Path(q['source']['member']['output']).read_bytes(),q['sha256']);h,ins=decode(d)
    leader=[]
    cases=[(0,[]),(-1,[]),(3,[(0,1,1),(1,2,1),(2,1,1)]),
           (3,[(1,1,1),(2,1,1),(2,1,1)]),(3,[(2,1,0),(2,1,0),(2,2,1)]),
           (3,[(1,1,-1),(0,1,1),(2,1,1)])]
    for count,records in cases:
        memory={34992496:0x10000,34992524:count}
        for i,(state,team,flag) in enumerate(records):
            a=0x10000+i*6336
            memory.update({a+468:state,a+3096:team,a+3124:flag})
        t=trace_slice(ins,169398,169460,memory,{20:1},halt_on_leave=True,capture_stack=True,limit=1024)
        leader.append({'count':count,'record_state_team_flag':records,'requested_team':1,'trace':t})
    leader_format=[]
    for slot in [-1,0,2]:
        memory={} if slot==-1 else {34091888+slot*880:0x50000}
        t=trace_slice(ins,185947,186431,memory,{76:slot})
        leader_format.append({'supplied_leader_return':slot,'trace':t})
    cache=[]
    obj,location=0x10000,0x20000
    for pointer,now,expiry in [(0,1000,0),(location,999,1000),(location,1000,1000),
                               (location,1001,1000),(location,-2147483640,2147483640)]:
        m={obj+848:pointer,34992532:now}
        if pointer:m[pointer+596]=expiry
        t=trace_slice(ins,268249,268279,m,{4236:obj},halt_on_leave=True,capture_stack=True)
        cache.append({'pointer':pointer,'now':now,'expiry':expiry,'trace':t})
    format_traces=[]
    for result in [0,location]:
        t=trace_slice(ins,268649,268676,{} if not result else {location+592:0x60000},
                      {24:result,44:0x70000,48:150},halt_on_leave=True,capture_stack=True)
        format_traces.append({'supplied_lookup_return':result,'trace':t})
    lists=[]
    for guarded,count,fields in [(1,3,[]),(0,0,[]),
          (0,3,[(1,8489281),(0,8489281),(1,0)]),
          (0,3,[(1,8489281),(1,8489281),(1,8489281)])]:
        m={34999636:guarded,34992508:count}
        for i,(name_present,raw_tag) in enumerate(fields):
            obj=34091368+i*880
            m.update({obj+536:0x80000 if name_present else 0,obj+540:raw_tag,
                      obj+524:0x90000+i*64,obj+592:0xa0000+i*64})
        t=trace_slice(ins,264977,265088,m,{36:34091368},limit=2048)
        lists.append({'guard':guarded,'count':count,'name_present_raw_tag':fields,'trace':t})
    references={}
    for value in [169397,268248,268637,34999640]:
        references[str(value)]=[]
        for j,x in enumerate(ins):
            if x['opcode']=='CONST' and x['operand']==value:
                entry=next(k for k in range(j,-1,-1) if ins[k]['opcode']=='ENTER')
                references[str(value)].append({'instruction':j,'containing_entry':entry,
                                               'window':ins[max(entry,j-4):j+7]})
    abi=json.loads(Path('docs/research/qvm/qagame.abi-candidates.json').read_text())
    if abi['sha256']!=q['sha256']:raise ValueError('ABI provenance changed')
    services=[r for r in abi['syscalls'] if r['number'] in [18,26,32]]
    extent=[]
    for address in [31128,31132,31136]:
        if address+4>h['data_length']:raise ValueError('box extent outside initialized data')
        offset=h['data_offset']+address
        extent.append({'vm_address':address,'raw_bits':struct.unpack_from('<I',d,offset)[0],
                       'float_value':struct.unpack_from('<f',d,offset)[0]})
    out={'box_extent_constants':extent,'abi_reference_revision':abi['reference_revision'],'service_candidates':services,'source':q['source'],'sha256':q['sha256'],
         'functions':{str(e):partition_function(ins,e,d,h) for e in [169397,264976,268248,268637]},
         'leader_scan_traces':leader,'leader_format_traces':leader_format,'cache_traces':cache,
         'location_format_traces':format_traces,'registration_traces':lists,'literal_references':references,
         'strings':{str(a):vm_string(d,h,a) for a in [93224,93227,92460,78042]},
         'limitations':'Static partitions and bounded synthetic traces, not original runtime/full QVM '
         'execution. Callees are recorded with zero placeholder returns; isolated lookup/leader returns are '
         'supplied. Floating-point distance/geometry and engine box/visibility calls are retained but not '
         'evaluated. Field types, cache writers, list lifecycle/ownership, real formatting and all-platform '
         'behavior remain open. Literal scans exclude aliases/computed references.'}
    write_json(Path('docs/research/chat-locations.json'),out)
    print('Recovered leader selection, cached location formatting and list-building traces')


if __name__=='__main__':main()