Calling Methods

📌Static vs non-static (Instance) methods

Feature

Static Method

Non-Static Method

Definition

Belongs to the class itself

Belongs to an instance of the class

Access

Called using the class name (ClassName.method())

Called on an object instance (this.method())

Frida Hooking

Hooked directly using varName.method.implementation

Hooked using this.method(...) inside implementation

Requires Instantiation?

❌ No (Doesn't need an object)

✅ Yes (Must have an object of the class)

Example in Java

public static void myMethod() {}

public void myMethod() {}

Example in Frida

varName.staticMethod.implementation = function() {...};

this.instanceMethod();

📌Calling Different Types of Methods in Frida

In Frida, you can interact with methods in Android apps, both static and instance methods. This section covers how to call these methods using Frida's JavaScript API.

📍Calling Static Methods

Static methods are called on the class itself. Here's the skeleton we can use to call a static method:

Java.perform(function() {
    // Get a reference to the MainActivity class
    var <class_reference> = Java.use("<package_name>.<className>");
    // Calling the static method nextLevel()
    <class_reference>.<static_method>();
});
  • Ex

📍Calling Instance Methods

To call a non-static (instance) method, you must first create an instance of the class. For example:

public class MyClass {
    public void myMethod() { /* ... */ }
}

// Correct usage:
MyClass obj = new MyClass();  // Create instance
obj.myMethod();               // Call instance method

Instance methods are called on instances of the class. There are two approaches to calling instance methods in Frida:

  • Approach 1: Creating a New Instance

    Java.perform(function() {
    		// Get a reference to the target class
        var class_reference = Java.use("<package_name>.<class>");
        // Create a new instance of the class
        var class_instance = class_reference.$new(); // Class Object
        // Call an instance method on the created object
        class_instance.<method>(); // Calling the method
    });
  • Approach 2: Finding Existing Instances and Overriding Properties

    Java.perform(function() {
        Java.scheduleOnMainThread(function() {
            Java.choose('packageName.ClassName', {
                onMatch: function(instance) {
                    try {
                        // Modify instance property
                        instance.propertyName.value = newValue;
    
                        // Call an instance method
                        instance.methodName();
                    } catch (e) {
                        console.error("Error: " + e.message);
                    }
                },
                onComplete: function() {
                    console.log("Finished scanning for instances");
                }
            });
        });
    });
  • Use this approach when dealing with Android framework components like Activity, Fragment, Service, or BroadcastReceiver.

Invoking Methods on an Existing Instance

In the MainActivity, there is a method called flag that is not invoked anywhere in the program. This method decrypts the flag and sets it in the textview. It’s a AES decrypt function. Additionally, we need to pass the value 1337 as an argument to bypass the if check. We encountered a similar situation in our previous post, but this time, it’s within MainActivity. Why not create another instance of MainActivity and call this method? Let’s try that.

  • Why Can’t We Create a New Instance of MainActivity?

    • When you create a new instance of MainActivity manually (e.g., using Java.use and $new()), you bypass the Android system’s lifecycle management.

    • Without going through onCreate(), onStart(), and onResume(), the activity won’t be properly initialized:

      • It won’t have access to the application context.

      • It won’t be attached to the UI thread or have a valid Looper (required for UI updates).

      • Any dependencies (e.g., views, resources) won’t be set up.

  • Solution: Using an Existing Instance

    • Instead of creating a new instance of MainActivity, we can use Frida to find and interact with the Android system's existing instance of MainActivity.

    • How does Frida help?

      • Frida allows you to hook into the running app and inspect its memory.

      • Using the Java.choose API, you can locate all instances of a specific class (in this case, MainActivity) at runtime.

    • Skeleton:

      Java.performNow(function() {
        Java.choose('<Package>.<Class_Name>', {
          onMatch: function(instance) {
            // TODO
          },
          onComplete: function() {}
        });
      });
    • Code:

      Java.performNow(function() {
        Java.choose('com.mobilehackinglab.FridaFive.MainActivity', {
          onMatch: function(instance) { // "instance" is the instance for the MainActivity
            console.log("Instance found");
            instance.flag(1337); // Calling the function
          },
          onComplete: function() {}
        });
      });


Last updated