41 lines
2.4 KiB
Python
41 lines
2.4 KiB
Python
"""Conservative AArch64 ALSA rate-call evidence. No title offsets or game execution."""
|
|
import hashlib
|
|
|
|
def alsa_rate(path):
|
|
from elftools.elf.elffile import ELFFile
|
|
from capstone import Cs,CS_ARCH_ARM64,CS_MODE_LITTLE_ENDIAN
|
|
from capstone.arm64 import ARM64_OP_IMM,ARM64_OP_REG
|
|
with path.open('rb') as f:
|
|
identity=hashlib.file_digest(f,'sha256').hexdigest();f.seek(0);elf=ELFFile(f)
|
|
if elf['e_machine']!='EM_AARCH64' or not elf.little_endian:return None
|
|
plt=elf.get_section_by_name('.plt');rela=elf.get_section_by_name('.rela.plt');text=elf.get_section_by_name('.text')
|
|
if not plt or not rela or not text:return None
|
|
sym=elf.get_section(rela['sh_link']);targets=set()
|
|
for index,rel in enumerate(rela.iter_relocations()):
|
|
if sym.get_symbol(rel['r_info_sym']).name=='snd_pcm_hw_params_set_rate':
|
|
targets.add(plt['sh_addr']+32+index*16)
|
|
if not targets:return None
|
|
decoder=Cs(CS_ARCH_ARM64,CS_MODE_LITTLE_ENDIAN);decoder.detail=True
|
|
import struct
|
|
evidence=[];blob=text.data();base=text['sh_addr']
|
|
for index,(word,) in enumerate(struct.iter_unpack('<I',blob[:len(blob)//4*4])):
|
|
if word>>26!=0x25:continue
|
|
immediate=word&0x3ffffff
|
|
if immediate>=0x2000000:immediate-=0x4000000
|
|
address=base+index*4
|
|
if address+immediate*4 not in targets:continue
|
|
start=max(0,index*4-32)
|
|
recent=list(decoder.disasm(blob[start:index*4],base+start))
|
|
rate=None;at=None
|
|
for previous in reversed(recent):
|
|
if previous.mnemonic.startswith('b') or previous.mnemonic=='ret':break
|
|
if previous.operands and previous.operands[0].type==ARM64_OP_REG and previous.reg_name(previous.operands[0].reg) in ('w2','x2'):
|
|
if previous.mnemonic=='mov' and len(previous.operands)==2 and previous.operands[1].type==ARM64_OP_IMM:
|
|
rate=previous.operands[1].imm;at=previous.address
|
|
break
|
|
if rate is None or not 8000<=rate<=192000:return None
|
|
evidence.append({'call_address':hex(address),'rate_load_address':hex(at),'rate':rate})
|
|
rates={r['rate'] for r in evidence}
|
|
if len(rates)!=1:return None
|
|
return {'sample_rate':rates.pop(),'binary_sha256':identity,'method':'AArch64 immediate x2 at ALSA set_rate PLT call','call_sites':evidence}
|