11import _ from 'lodash' ;
2+ import * as stream from 'stream' ;
3+ import * as FridaJs from 'frida-js' ;
24
35import { Interceptor } from ".." ;
46import { HtkConfig } from '../../config' ;
57
68import { createAdbClient } from '../android/adb-commands' ;
7- import { FridaHost , FridaTarget } from './frida-integration' ;
9+ import { FridaHost , FridaTarget , killProcess } from './frida-integration' ;
810import {
911 getAndroidFridaHosts ,
1012 getAndroidFridaTargets ,
@@ -58,6 +60,9 @@ export class FridaAndroidInterceptor implements Interceptor {
5860 }
5961 }
6062
63+ private fridaServers : { [ proxyPort : number ] : Array < stream . Readable > } = { } ;
64+ private interceptedApps : { [ proxyPort : number ] : Array < FridaJs . FridaAgentSession > } = { } ;
65+
6166 async activate (
6267 proxyPort : number ,
6368 options :
@@ -68,24 +73,51 @@ export class FridaAndroidInterceptor implements Interceptor {
6873 if ( options . action === 'setup' ) {
6974 await setupAndroidHost ( this . adbClient , options . hostId ) ;
7075 } else if ( options . action === 'launch' ) {
71- await launchAndroidHost ( this . adbClient , options . hostId ) ;
76+ const fridaServer = await launchAndroidHost ( this . adbClient , options . hostId ) ;
77+
78+ // Track this server stream, so we can close it to stop the server later
79+ this . fridaServers [ proxyPort ] = this . fridaServers [ proxyPort ] ?? [ ] ;
80+ this . fridaServers [ proxyPort ] . push ( fridaServer ) ;
81+ fridaServer . on ( 'close' , ( ) => {
82+ _ . remove ( this . fridaServers [ proxyPort ] , fridaServer ) ;
83+ } ) ;
7284 } else if ( options . action === 'intercept' ) {
73- await interceptAndroidFridaTarget (
85+ const fridaSession = await interceptAndroidFridaTarget (
7486 this . adbClient ,
7587 options . hostId ,
7688 options . targetId ,
7789 this . config . https . certContent ,
7890 proxyPort
7991 ) ;
92+
93+ // Track this session, so we can close it to stop the interception later
94+ this . interceptedApps [ proxyPort ] = this . interceptedApps [ proxyPort ] ?? [ ] ;
95+ this . interceptedApps [ proxyPort ] . push ( fridaSession ) ;
8096 } else {
8197 throw new Error ( `Unknown Frida interception command: ${ ( options as any ) . action ?? '(none)' } ` )
8298 }
8399 }
84100
85101 async deactivate ( proxyPort : number ) : Promise < void | { } > {
102+ this . fridaServers [ proxyPort ] ?. forEach ( serverStream => {
103+ serverStream . destroy ( ) ;
104+ } ) ;
105+
106+ await Promise . all ( this . interceptedApps [ proxyPort ] ?. map ( async fridaSession => {
107+ await killProcess ( fridaSession ) . catch ( ( ) => { } ) ;
108+ } ) ) ;
86109 }
87110
88111 async deactivateAll ( ) : Promise < void | { } > {
112+ const allPorts = new Set ( [
113+ ...Object . keys ( this . fridaServers ) ,
114+ ...Object . keys ( this . interceptedApps )
115+ ] ) ;
116+
117+ await Promise . all (
118+ [ ...allPorts ]
119+ . map ( port => this . deactivate ( Number ( port ) ) )
120+ ) ;
89121 }
90122
91123}
0 commit comments