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

XFEEDToolBox

【WinUI】XFE精英危险工具箱

公开
关注 0 Fork 0 Star 0
UTF-8
"""Observe the selected ship's original throttle setter/clear calls; no control commands or writes."""
import argparse,hashlib,json,time
from pathlib import Path
import frida
p=argparse.ArgumentParser(description=__doc__)
p.add_argument('--pid',type=int,required=True);p.add_argument('--profile',type=Path,required=True);p.add_argument('--snapshot',type=Path,required=True);p.add_argument('--output',type=Path,required=True)
p.add_argument('--seconds',type=int,default=90,choices=range(5,121));a=p.parse_args()
profile=json.loads(a.profile.read_text(encoding='utf-8-sig'));snapshot=json.loads(a.snapshot.read_text(encoding='utf-8-sig'))
if snapshot['pid']!=a.pid or snapshot['gameSha256']!=profile['sha256'] or hashlib.sha256(Path(profile['image']).read_bytes()).hexdigest()!=profile['sha256']:raise ValueError('Build/process mismatch')
b={'pid':a.pid,'controller':snapshot['physics'][0]['controller'],'root':snapshot['physics'][0]['inputRoot'],'life':snapshot['components'][0]['lifecycle'],'entity':snapshot['player']['entityId']}
source='const PROFILE='+json.dumps(profile)+';const B='+json.dumps(b)+r''';
const game=Process.getModuleByName('EliteDangerous64.exe');
if(Process.id!==B.pid||game.path.toLowerCase()!==PROFILE.image.toLowerCase())throw Error('Process changed');
const controller=ptr(B.controller),root=ptr(B.root),life=ptr(B.life);
function valid(){return life.add(0xC0).readU32()===8&&life.add(0xB0).readU64().toString()===B.entity&&root.add(0x2F8).readPointer().equals(controller);}
function where(p){const m=Process.findModuleByAddress(p);return m===null?{unmapped:true}:{module:m.name,rva:p.sub(m.base).toString()};}
for(const [rva,kind] of [[0x25E5DD0,'set'],[0x25E9420,'clear']]){
Interceptor.attach(game.base.add(rva),{onEnter(args){this.selected=args[0].equals(controller)&&valid();if(this.selected){this.before=controller.add(0x680).readFloat();this.caller=this.returnAddress;this.axes=Array.from({length:6},(_,i)=>root.add(0x70+i*16).readFloat());}},onLeave(){if(!this.selected||!valid())return;const after=controller.add(0x680).readFloat();if(after!==this.before)send({kind:'throttle-'+kind,at:new Date().toISOString(),before:this.before,after,caller:where(this.caller),axes:this.axes,thread:Process.getCurrentThreadId()});}});
}
send({kind:'ready',pid:Process.id,screenUse:false,controlCommandsSent:0});
'''
with a.output.open('x',encoding='utf-8') as out:
    session=frida.attach(a.pid)
    try:
        script=session.create_script(source)
        def message(m,data):
            row=m.get('payload',m);out.write(json.dumps(row)+'\n');out.flush();print(json.dumps(row),flush=True)
        script.on('message',message);script.load();time.sleep(a.seconds);script.unload()
    finally:session.detach()