Download scripts/analyze_auth_queries.py from nmarshall/urt-rs: direct link, hf CLI and curl.
- Browser
- Download file 8.29 kB
-
https://huggingface.co/nmarshall/urt-rs/resolve/main/scripts/analyze_auth_queries.py
- Command line
-
hf download hf://nmarshall/urt-rs/scripts/analyze_auth_queries.py
-
curl -L -o analyze_auth_queries.py https://huggingface.co/nmarshall/urt-rs/resolve/main/scripts/analyze_auth_queries.py
8.29 kB
| #!/usr/bin/env python3 | |
| """Bounded authentication selector, command-role and internal-mode evidence.""" | |
| import json | |
| from pathlib import Path | |
| from analyze_auth_announcements import recover_table | |
| 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 byte_string(address, value): | |
| return {address+i: b for i, b in enumerate(value+b'\0')} | |
| def cleaned_name(ins, value): | |
| address = 0x10000 | |
| t = trace_slice(ins, 70242, 70383, {}, {44: address}, limit=10000, | |
| byte_memory=byte_string(address, value)) | |
| result = [] | |
| for at in range(address, address+len(value)+1): | |
| b = t['byte_memory'][at] | |
| if not b: | |
| break | |
| result.append(b) | |
| return {'input_hex': value.hex(), 'output_hex': bytes(result).hex(), 'trace': t} | |
| def substring_trace(ins, haystack, needle): | |
| # The length-call results are supplied explicitly; the byte comparison runs. | |
| empty = not haystack or not needle or len(needle)>len(haystack) | |
| return trace_slice(ins, 69746, 69760 if empty else 69910, {}, | |
| {24: len(needle), 28: len(haystack), 72: 0x10000, 76: 0x20000}, | |
| limit=10000, byte_memory={**byte_string(0x10000, haystack), **byte_string(0x20000, needle)}) | |
| def main(): | |
| qvm = json.loads(Path('docs/research/qvm/qagame.json').read_text()) | |
| data = verified(Path(qvm['source']['member']['output']).read_bytes(), qvm['sha256']) | |
| h, ins = decode(data) | |
| rows = json.loads(Path('docs/research/game-cvars.json').read_text()) | |
| if rows['sha256'] != qvm['sha256']: | |
| raise ValueError('registry provenance mismatch') | |
| by_name = {r['name']: r for r in rows['registry']['rows']} | |
| for name, address, offset in [('auth_enable',35003268,12),('dedicated',34090492,12), | |
| ('auth_groups',35001792,16),('auth_notoriety',35002084,12), | |
| ('auth_cmds_friend',35001200,16),('auth_cmds_member',35000904,16), | |
| ('auth_cmds_referee',35000608,16)]: | |
| if by_name[name]['mirror_address']+offset != address: | |
| raise ValueError('cvar mirror identity mismatch') | |
| classify = [] | |
| for text in [b'',b'0',b'01',b'63',b'123',b'-1',b'+1',b' 1',b'1 ',b'1x',b'Player']: | |
| digit_only = all(48 <= x <= 57 for x in text) | |
| trace = trace_slice(ins, 253562, 253605 if digit_only else 253669, {}, {376: 0x10000}, | |
| limit=2048, byte_memory=byte_string(0x10000,text)) | |
| classify.append({'input_hex':text.hex(),'digit_only':digit_only,'trace':trace}) | |
| slots = [] | |
| base = 0x30000 | |
| for slot in [-1,0,3,4]: | |
| valid = 0 <= slot < 4 | |
| t = trace_slice(ins,253612,253641 if valid else 253638,{34992524:4},{360:slot}) | |
| slots.append({'slot':slot,'maxclients':4,'trace':t}) | |
| connection = [] | |
| for state in [-1,0,1,2]: | |
| slot=3;record=base+slot*6336 | |
| t=trace_slice(ins,253641,253666 if state==0 else 253875, | |
| {34992496:base,record+468:state},{352:slot}) | |
| returned = None if state==0 else trace_slice(ins,253875,253889,{34992496:base},{88:record}) | |
| connection.append({'state_raw':state,'slot':slot,'trace':t,'success_tail':returned}) | |
| substrings=[] | |
| for haystack,needle in [(b'AlphaBravo',b'BRAVO'),(b'AlphaBravo',b'phab'),(b'Alpha',b'Gamma'), | |
| (b'bigtext say',b'ay'),(b'bigtext say',b'say map'),(b'public',b'PUBLIC'), | |
| (b'',b'a'),(b'abc',b''),(b'ab',b'abc')]: | |
| substrings.append({'haystack_hex':haystack.hex(),'needle_hex':needle.hex(), | |
| 'trace':substring_trace(ins,haystack,needle)}) | |
| table=recover_table(data,h,ins,29196,2,8,167097,167279) | |
| table_memory={r['vm_address']:r['target_instruction'] for r in table['rows']} | |
| role_targets={r['value']:r['target_instruction'] for r in table['rows']} | |
| roles=[] | |
| for role in [-1,0,1,2,3,4,5,6,7,8,9]: | |
| target=role_targets.get(role,167275) | |
| t=trace_slice(ins,167148,target,{**table_memory,0x20000+520:0x30000,0x30000+3688:role},{68:0x20000}) | |
| roles.append({'role':role,'target':target,'trace':t}) | |
| permission_gates=[] | |
| for mode,entity,command,state,role in [(0,0x20000,b'whois',2,2),(1,0,b'whois',2,2), | |
| (1,0x20000,b'',2,2),(1,0x20000,b'whois',1,2),(1,0x20000,b'whois',2,1), | |
| (1,0x20000,b'whois',2,2),(3,0x20000,b'whois',2,8)]: | |
| stop = 167103 if mode<1 else 167131 if not entity or not command or state!=2 else 167145 if role<2 else 167148 | |
| t=trace_slice(ins,167098,stop,{35017616:mode,entity+520:0x30000,0x30000+468:state,0x30000+3688:role}, | |
| {68:entity,72:0x40000},byte_memory=byte_string(0x40000,command)) | |
| permission_gates.append({'mode':mode,'entity':entity,'command_hex':command.hex(),'state_raw':state, | |
| 'role':role,'reaches_role_switch':stop==167148,'trace':t}) | |
| routes=[] | |
| for route,start,stop,locals_map in [('client',189074,189083,{3348:0x20000,3120:0x40000}), | |
| ('console',263048,263055,{})]: | |
| routes.append({'route':route,'trace':trace_slice(ins,start,stop,{},locals_map)}) | |
| modes=[] | |
| for groups,notoriety in [(0,0),(1,0),(0,5),(1,5),(0,-1)]: | |
| modes.append({'groups_length':groups,'notoriety':notoriety, | |
| 'trace':trace_slice(ins,308,389,{35002084:notoriety},{80:groups})}) | |
| disabled=[] | |
| for cause,start,memory,locals_map in [ | |
| ('enable_not_one',172,{35003268:0},{}),('bad_engine',201,{}, {68:0}), | |
| ('not_dedicated_two',224,{34090492:1},{}),('no_features_tail',279,{}, {76:0}), | |
| ('unresolved_address',469,{35017620:0},{})]: | |
| disabled.append({'cause':cause,'trace':trace_slice(ins,start,838,memory,locals_map)}) | |
| refs=[];callers=[];entry=None | |
| for i in ins: | |
| at=i['index'] | |
| if i['opcode']=='ENTER':entry=at | |
| if i['opcode']=='CONST' and i['operand']==35017616: | |
| refs.append({'instruction':at,'entry':entry,'window':ins[max(entry,at-4):at+7]}) | |
| if i['opcode']=='CALL' and at and ins[at-1]['opcode']=='CONST' and ins[at-1]['operand']==1264: | |
| callers.append({'instruction':at,'entry':entry,'window':ins[at-22:at+3]}) | |
| output={'source':qvm['source'],'sha256':qvm['sha256'], | |
| 'functions':{str(e):partition_function(ins,e,data,h) for e in [171,253561,69723,70241,167097]}, | |
| 'digit_classification_traces':classify,'slot_bound_traces':slots,'slot_connection_traces':connection, | |
| 'clean_name_traces':[cleaned_name(ins,s) for s in [b'^1Alpha^7',b'A^^B',b'A^xB',b'A\x01\x1f\x7f\x80B']], | |
| 'substring_traces':substrings,'permission_role_table':table,'permission_role_traces':roles, | |
| 'permission_gate_traces':permission_gates, | |
| 'query_direct_callers':callers,'dispatch_traces':routes, | |
| 'dispatch_windows':{'client_prefix':ins[188019:188059], | |
| 'client_precheck':ins[188059:188105],'client_match':ins[189059:189085], | |
| 'console_match':ins[263034:263059],'console_argv':ins[262012:262040]}, | |
| 'mode_selection_traces':modes,'disabled_mode_traces':disabled,'mode_literal_references':refs, | |
| 'strings':{str(at):vm_string(data,h,at) for at in [77268,87076,38124,38397,38385,38139,38107,38095, | |
| 38081,38073,38060,38053,37794,67226,91861,91825,91796,91759,91747]}, | |
| 'limitations':'Static supplied qagame plus bounded instruction slices, not a complete QVM/runtime. ' | |
| 'All CALLs are recorded and return zero placeholders. Integer parser and substring length-call results ' | |
| 'are supplied fixture inputs; selected slices exclude preceding conditions. No complete selector, ' | |
| 'permission lifecycle, engine registration/config timing or network/runtime conformance claim.'} | |
| write_json(Path('docs/research/auth-queries.json'),output) | |
| print(f'Recovered selector helpers, role table, {len(callers)} query callers and {len(refs)} internal-mode references') | |
| if __name__=='__main__': | |
| main() | |