import json,sys,time,frida
A=json.load(open('/root/ants/force_addrs.json'))
JS=r"""
var A=%s; var base=null; var ppThis=null; var done=false;
function ins(){var m=Process.findModuleByName('libil2cpp.so'); if(m===null)return false; base=m.base;
 var Awake=new NativeFunction(base.add(A['PlayerProfile::Awake/0']),'void',['pointer','pointer']);
 var Start=new NativeFunction(base.add(A['PlayerProfile::Start/0']),'void',['pointer','pointer']);
 Interceptor.attach(base.add(A['PlayerProfile::.ctor/0']),{onEnter:function(a){ppThis=a[0];}});
 ['PlayerProfile::OnSectionChange/2','PlayerProfile::LoadProfile/1','FE.EnterVault::Awake/0','FE.EnterVault::Show/0','FE.Director::EnterMenuScene/2'].forEach(function(n){
   Interceptor.attach(base.add(A[n]),{onEnter:function(){send({t:'hit',n:n});}});});
 var iv=setInterval(function(){if(ppThis!==null&&!done){done=true;
   try{ send({t:'log',m:'force Awake'}); Awake(ppThis,ptr(0));
        send({t:'log',m:'force Start'}); Start(ppThis,ptr(0));
        send({t:'log',m:'both returned OK'}); }
   catch(e){ send({t:'log',m:'threw: '+e}); }
   clearInterval(iv);}},50);
 send({t:'log',m:'ready'}); return true;}
if(!ins()){var t=setInterval(function(){if(ins())clearInterval(t);},100);}
""" % json.dumps(A)
dev=frida.get_device_manager().add_remote_device('127.0.0.1:27042')
pid=dev.spawn(['se.foglo.svt']); ses=dev.attach(pid); sc=ses.create_script(JS)
hits={}
def om(m,d):
    if m['type']!='send':print('!!',m);return
    p=m['payload']
    if p['t']=='hit':
        hits[p['n']]=hits.get(p['n'],0)+1
        if hits[p['n']]<=2: print('%7.2fs HIT %s'%(time.time()-t0,p['n']))
    else: print('%7.2fs %s'%(time.time()-t0,p['m']))
sc.on('message',om); sc.load(); t0=time.time(); dev.resume(pid)
time.sleep(int(sys.argv[1]) if len(sys.argv)>1 else 70)
print('\n=== hits ==='); [print('  %-36s %d'%(k,v)) for k,v in sorted(hits.items(),key=lambda x:-x[1])]
