note Slow Binder Call

by
28 views 164b14e0...

Description

use StrictMode.noteSlowCall to mark common slow binder call on main thread(IActivityManager, IPackageManager, IConnectivityManager)

How to Use

Download the script and run it with Frida CLI:

Download Script

Then run with Frida:

frida -U -f YOUR_PACKAGE_NAME -l note-slow-binder-call.js

Replace YOUR_PACKAGE_NAME with the target app's package name.

Source Code

JavaScript
Java.perform(function() {
	
	const strictmode = Java.use('android.os.StrictMode')
	//【Note Slow Call】
	// 1. ContextWrapper(cover IActivityManager 80% slow binder call)
	const contextWrapper = Java.use("android.content.ContextWrapper")
	// 1.1 sendBroadcast
	contextWrapper.sendBroadcast.overload('android.content.Intent').implementation = function(intent) {
	
		strictmode.noteSlowCall("sendBroadcast(Intent)")
		return this.sendBroadcast(intent);
	}
	
	contextWrapper.sendBroadcast.overload('android.content.Intent', 'java.lang.String').implementation = function(intent, permission) {
	
	
		strictmode.noteSlowCall("sendBroadcast(Intent, String)")
		this.sendBroadcast(intent, permission)
	}
	
	contextWrapper.sendBroadcast.overload('android.content.Intent', 'java.lang.String', 'android.os.Bundle').implementation = function(intent, permission, bundle) {
		
		strictmode.noteSlowCall("sendBroadcast(Intent, String, Bundle)")
		return this.sendBroadcast(intent, permission, bundle)
	}
	
	// 1.2 registerReceiver
	contextWrapper.registerReceiver.overload('android.content.BroadcastReceiver', 'android.content.IntentFilter', 'java.lang.String', 'android.os.Handler').implementation = function(recv, filter, permission, handler) {
		
		strictmode.noteSlowCall("registerReceiver(BroadcastReceiver, IntentFilter, String, Handler)")
		return this.registerReceiver(recv, filter, permission, handler)
	}
	
	contextWrapper.registerReceiver.overload('android.content.BroadcastReceiver', 'android.content.IntentFilter', 'java.lang.String', 'android.os.Handler', 'int').implementation = function(recv, filter, permission, handler, flags) {
		
		strictmode.noteSlowCall("registerReceiver(BroadcastReceiver, IntentFilter, String, Handler, int)")
		return this.registerReceiver(recv, filter, permission, handler, flags)
	}

	contextWrapper.registerReceiver.overload('android.content.BroadcastReceiver', 'android.content.IntentFilter', 'int').implementation = function(recv, filter, flags) {
		
		strictmode.noteSlowCall("registerReceiver(BroadcastReceiver, IntentFilter, int)")
		return this.registerReceiver(recv, filter, flags)
	}
	
	contextWrapper.registerReceiver.overload('android.content.BroadcastReceiver', 'android.content.IntentFilter').implementation = function(recv, filter) {
		
		strictmode.noteSlowCall("registerReceiver(BroadcastReceiver, IntentFilter)")
		return this.registerReceiver(recv, filter)
	}
	
	// 1.3 updateServiceGroup
	contextWrapper.updateServiceGroup.overload('android.content.ServiceConnection', 'int', 'int').implementation = function(conn, group, importance) {
		
		strictmode.noteSlowCall("updateServiceGroup(ServiceConnection, group, importance)")
		return this.updateServiceGroup(conn, group, importance)
	}
	
	// 1.4 startService
	contextWrapper.startService.overload('android.content.Intent').implementation = function(intent) {
		
		strictmode.noteSlowCall("startService(Intent)")		
		return this.startService(intent)
	}
	
	// 1.5 bindService
	contextWrapper.bindService.overload('android.content.Intent', 'android.content.ServiceConnection', 'int').implementation = function(service, conn, flags)  {

		strictmode.noteSlowCall("bindService(Intent, ServiceConnection, int)")
		return this.bindService(service, conn, flags)
	}
	
	contextWrapper.bindService.overload('android.content.Intent', 'android.content.ServiceConnection',  'android.content.Context$BindServiceFlags').implementation = function(service, conn, flags) {
		
		strictmode.noteSlowCall("bindService(Intent, ServiceConnection, Context.BindServiceFlags)")
		return this.bindService(service, conn, flags)
	}
	
	contextWrapper.bindService.overload('android.content.Intent', 'int', 'java.util.concurrent.Executor', 'android.content.ServiceConnection').implementation = function(intent, flags, executor, conn) {
		
		strictmode.noteSlowCall("bindService(Intent, int, Executor, ServiceConnection)")
		return this.bindService(intent, flags, executor, conn)
	}
	
	contextWrapper.bindService.overload('android.content.Intent', 'android.content.Context$BindServiceFlags', 'java.util.concurrent.Executor', 'android.content.ServiceConnection').implementation = function(intent, flags, executor, conn) {
		
		strictmode.noteSlowCall("bindService(Intent, Context.BindServiceFlags, Executor, ServiceConnection)")
		return this.bindService(intent, flags, executor, conn)
	}
	
	// 1.6 unbindService
	contextWrapper.unbindService.overload('android.content.ServiceConnection').implementation = function(conn) {
		
		strictmode.noteSlowCall("unbindService(ServiceConnection)")
		return this.unbindService(conn)
	}
	
	// 2. PackageManager(cover IPackageManager 80% slow binder call)
	const packageManager = Java.use("android.content.pm.PackageManager")
	
	// 2.1 getApplicationInfo
	packageManager.getApplicationInfo.overload('java.lang.String', 'int').implementation = function(name, flags) {
		
		strictmode.noteSlowCall("getApplicationInfo(String, int)")
		return this.getApplicationInfo(name, flags)
	}
	
	packageManager.getApplicationInfo.overload('java.lang.String', 'android.content.pm.PackageManager$ApplicationInfoFlags').implementation = function(name, flags) {
		
		strictmode.noteSlowCall("getApplicationInfo(ApplicationInfoFlags, int)")
		return this.getApplicationInfo(name, flags)
	}
	
	// 2.2 getPackageInfo
	packageManager.getPackageInfo.overload('java.lang.String', 'int').implementation = function(packageName, flags) {
		
		strictmode.noteSlowCall("getPackageInfo(String, int)")
		return this.getPackageInfo(packageName, flags)
	}
	
	packageManager.getPackageInfo.overload('java.lang.String', 'android.content.pm.PackageManager$PackageInfoFlags').implementation = function(packageName, flags) {

		strictmode.noteSlowCall("getPackageInfo(String, PackageInfoFlags)")
		return this.getPackageInfo(packageName, flags)
	}
	
	packageManager.getPackageInfo.overload('android.content.pm.VersionedPackage', 'android.content.pm.PackageManager$PackageInfoFlags').implementation = function(versionedPackage, flags) {
		
		strictmode.noteSlowCall("getPackageInfo(VersionedPackage, PackageInfoFlags)")		
		return this.getPackageInfo(versionedPackage, flags)
	}
	
	packageManager.getPackageInfo.overload('android.content.pm.VersionedPackage', 'int').implementation = function(versionedPackage, flags) {
	
		strictmode.noteSlowCall("getPackageInfo(VersionedPackage, int)")
		return this.getPackageInfo(versionedPackage, flags)
	}
	
	// 2.3 getActivityInfo
	packageManager.getActivityInfo.overload("android.content.ComponentName", "int").implementation = function(componentName, flags) {
		
		strictmode.noteSlowCall("getActivityInfo(ComponentName, int)")
		return this.getActivityInfo(componentName, flags)
	}
	
	packageManager.getActivityInfo.overload("android.content.ComponentName", "android.content.pm.PackageManager$ComponentInfoFlags").implementation = function(componentName, flags) {
		
		strictmode.noteSlowCall("getActivityInfo(ComponentName, ComponentInfoFlags)")
		return this.getActivityInfo(componentName, flags)
	}
	
	// 2.4 queryIntentActivities
	packageManager.queryIntentActivities.overload('android.content.Intent', 'android.content.pm.PackageManager$ResolveInfoFlags').implementation = function(intent, flags) {
		
		strictmode.noteSlowCall("queryIntentActivities(Intent, ResolveInfoFlags)")
		return this.queryIntentActivities(intent, flags)
	}
	
	packageManager.queryIntentActivities.overload('android.content.Intent', 'int').implementation = function(intent, flags) {
		
		strictmode.noteSlowCall("queryIntentActivities(Intent, int)")
		return this.queryIntentActivities(intent, flags)
	}
	
	// 2.5 queryIntentServices
	packageManager.queryIntentServices.overload('android.content.Intent', 'int').implementation = function(intent, flags) {
		
		strictmode.noteSlowCall("queryIntentServices(Intent,  int)")
		return this.queryIntentServices(intent, flags)
	}
	
	packageManager.queryIntentServices.overload('android.content.Intent', 'android.content.pm.PackageManager$ResolveInfoFlags').implementation = function(intent, flags) {
		
		strictmode.noteSlowCall("queryIntentServices(Intent,  ResolveInfoFlags)")
		return this.queryIntentServices(intent, flags)
	}
	
	// 3 android.net.ConnectivityManager
	const connectivityManager = Java.use("android.net.ConnectivityManager")
	
	// 3.1 getActiveNetworkInfo
	connectivityManager.getActiveNetworkInfo.implementation = function() {
		
		strictmode.noteSlowCall("getActiveNetworkInfo()")
		return this.getActiveNetworkInfo()
	}
	
	// 3.2 getNetworkInfo
	connectivityManager.getNetworkInfo.overload('int').implementation = function(networkType) {
		
		strictmode.noteSlowCall("getNetworkInfo(int)")
		return this.getNetworkInfo(networkType)
	}
	
	connectivityManager.getNetworkInfo.overload('android.net.Network').implementation = function(network) {
		
		strictmode.noteSlowCall("getNetworkInfo(Network)")
		return this.getNetworkInfo(network)
	}
	
	// 3.3 getNetworkCapabilities(Network network)
	connectivityManager.getNetworkCapabilities.overload('android.net.Network').implementation = function(network) {
		
		strictmode.noteSlowCall("getNetworkCapabilities(Network)")
		return this.getNetworkCapabilities(network)
	}
	
	// 3.4 getActiveNetwork
	connectivityManager.getActiveNetwork.implementation = function() {
		
		strictmode.noteSlowCall("getActiveNetwork()")
		return this.getActiveNetwork()
	}
	
	// 【enable StrictMode】
	// Looper, Handler, Runnable to enable StrictMode on mainthread
	const looperClz = Java.use('android.os.Looper')
	const handlerClz = Java.use('android.os.Handler')
	const runnableIntf = Java.use('java.lang.Runnable')
	
	// StrictMode and related classes to turn on StrictMode
	const tpBuilder = Java.use('android.os.StrictMode$ThreadPolicy$Builder')	
	const androidBlockGuardPolicy = Java.use('android.os.StrictMode$AndroidBlockGuardPolicy')
	
	var mainLooper = looperClz.getMainLooper()
	var handler = handlerClz.$new(mainLooper)
	
	/* used to debug noteSlowCall, comment out
	  
	strictmode.noteSlowCall.implementation = function(name) {
		
		this.noteSlowCall(name)
	}
	
	strictmode.tooManyViolationsThisLoop.implementation = function() {
		
		var ret = this.tooManyViolationsThisLoop()
		
		return ret
	}
	
	androidBlockGuardPolicy.onNoteSlowCall.implementation = function(name) {
		
		
		return this.onNoteSlowCall()
	}
	*/
	
	// register new Runnable class to enable StrictMode
	// if "Error: java.io.IOException: Permission denied" happens, adb shell setenforce 0 to turn off selinux
	var runnableClz = Java.registerClass({
        name: 'EnforceStrictModeRunnable',
        implements: [runnableIntf],
        methods: {
            run: function() {
				
				// enable log and flash screen for thread policy
				
				const tp = tpBuilder.$new().detectCustomSlowCalls().penaltyLog().penaltyFlashScreen().build()
				strictmode.setThreadPolicy(tp)
            }
        }
    });
    
    // post runnable class to main looper to enable strictmode
	handler.post(runnableClz.$new());
})
Share this script:
Twitter LinkedIn

Comments

Login or Sign up to leave a comment.
Loading comments...