Inheritance

Working with inheritance

**** NOTE: BLOG MOVED TO https://cmrodriguez.me/ ****

Java as a OOP language has the inheritance feature. When one class inherits from another class in Java, the two classes take on certain roles. The class that extends (inherits from another class) is the subclass and the class that is being extended (the class being inherited from) is the superclass. In other words, the subclass extends the superclass. Or, the subclass inherits from the superclass. The subclass inherits the attributes and methods from their parents, so a subclass behaves like a superclass.

As an example in the project I created a Figure class, and a Circle and Square subclasses. I'll be showing some java features with these two classes.

I created a class in the Android application called TestInheritance that has a method that returns the perimeter of a figure. As it can be seen in the code:

public static double getPerimeter(Figure figure) {
    return figure.perimeter();
}

As it can be seen it receives a "Figure" class type. As the Circle and Square classes are figures (because of inheritance), you can send any instance of these two classes to the getPerimeter method. Let's do this with Frida:

var TestInheritance = Java.use("com.blog.testfrida.inheritance.TestInheritance");
var Square = Java.use("com.blog.testfrida.inheritance.Square");

var squareInstance = Square.$new(5);

console.log("square perimeter: " + TestInheritance.getPerimeter(squareInstance)); 

In Frida you can work with inherited classes as you would do directly in Java, as the methods automatically casts the object to the right type.

The method TestInheritance.getCircle returns a Figure type:

public static double getPerimeter(Figure figure) {
    return figure.perimeter();
}

When we retrieve the value from Frida and check the class:

var figureInstance = TestInheritance.getCircle();
console.log(figureInstance.$className);

we get that the className is 'com.blog.testfrida.inheritance.Circle'. But when we try to use a method that is in the Circle only (getCircleName) we get that the method is undefined. This means the object is casted to a Figure:

var figureInstance = TestInheritance.getCircle();
if (figureInstance.getCircleName === undefined) {
    console.log("Instance is figure, the getCircleName does not exist.");
} else {
    console.log(figureInstance.getCircleName());
}

To access the circle method, we should cast it:

circleInstance = Java.cast(figureInstance,Circle);
console.log(circleInstance.getCircleName());

Sometimes in Java we want to reuse some code of a parent class, but we want to add some component that exists or makes sense only in the subclass. As an example a constructor that sets all the private attributes to a default value. As an example, in the Android application I created two classes. One is SuperClass, and the other SubClass. In the SuperClass we have the "superValue". In the constructor we set its value to 10:

public SuperClass() {
    superValue = 10;
}

The SubClass has two attributes that are being set in the constructor.

public SubClass() {
    super();
    subValue = 10;
    setValue = 10;
}

To avoid copy the SuperClass content to the SubClass constructor (in some cases it isn't even possible), Java has a "super" attribute that points to the SuperClass object. We can use it to call the SuperClass method, so then when we use the SubClass method to get the superValue, we'll see that it was set to 10.

Let's do this on Frida:

//In this case I rewrote a new function that has a super implementation
SubClass.$init.implementation = function () {
    var superInheritance = Java.cast(this,SuperClass);
    superInheritance.$init();
    this.subValue.value = 25;
}

There a couple of things to tell about this example. When you want to change or intercept a constructor, you need to modify the $init function in Frida. To call the super class, you need to cast the "this" variable (reference to itself).

Last updated