Установка члена в текущем классе с помощью Frida

#javascript #java #android #reverse-engineering #frida

Вопрос:

Я подключаю определенную функцию в Frida, которая использует код:

 this.carrier.getId()
 

Однако на данный момент this.carrier еще не установлен, что приводит к сбою приложения.
Итак, я подумываю о том, чтобы вручную установить этот член в текущей функции в классе. Таким образом, этот носитель будет существовать к моменту выполнения кода.
Проблема в том, что при этом я сталкиваюсь с проблемой.

Пока это то, что я получил:

 Java.perform(function () {
    var SignUpActivity = Java.use('com.app.features.authentication.SignUpActivity');
    SignUpActivity.validatePhoneNumber.implementation = function() {
        
        var Carrier = Java.use("com.app.Carrier");
        this.carrier = Carrier.$new();
        console.log(this.carrier) // This prints "[object Object]"
        console.log(this.carrier.setId) // This prints "undefined"
        this.carrier.setId(123); // crashes

    };
});
 

Код носителя:

 package com.app;

import android.os.Parcel;
import android.os.Parcelable;

public class Carrier implements Parcelable {

    private int id;
    private String name;
    private String officeTerminalAddress;

    public Carrier() {
    }

    protected Carrier(Parcel parcel) {
        this.id = parcel.readInt();
        this.name = parcel.readString();
        this.officeTerminalAddress = parcel.readString();
    }

    public int getId() {
        return this.id;
    }

    public void setId(int i) {
        this.id = i;
    }

}
 

Ответ №1:

Похоже, что общая проблема в Frida заключается в том, что способ доступа к полям в Frida отличается.

Frida использует код JavaScript, поэтому он не может напрямую обрабатывать объекты, отличные от JavaScript. Поэтому он оборачивает «собственные» объекты (в данном случае объекты Android Java) в объекты JavaScript.

Если вы сейчас вызовете Frida this.carrier , вы получите оболочку JavaScript Frida, а не экземпляр Java Carrier, на который вы нацелены.

Конечно, оболочка JavaScript Frida не имеет методов, которые вы пытаетесь вызвать, поэтому this.carrier.setId(123); всегда будет терпеть неудачу.

Доступ к полю Java с помощью Frida

Чтобы получить доступ к полю, вам всегда нужно обращаться .value к нему, чтобы получить фактическое значение:

Так что, если вы хотите this.carrier , вы должны использовать this.carrier.value .

Кроме того, рекомендуется обращаться к полю по его имени с дополнительным подчеркиванием впереди. В противном случае в запутанных приложениях может оказаться, что есть поле и метод с тем же именем. В таком случае Frida не знает, хотите ли вы получить доступ к полю carrier или носителю метода.

Заключение если вы хотите получить доступ к полю экземпляра класса Java в приложении для Android с помощью Frida, рекомендуемый способ

 this._carrier.value
 

Итак, для записи значения поля вы должны вызвать

 this._carrier.value = ...
 

И то же самое для чтения.

Ссылка на страницы справки Frida

Это также описано на страницах Frida, например, здесь:

Обратите внимание, что мы используем this.m.value = 0 вместо this.m = 0 для установки значения поля. Если в этом классе также есть метод с именем m, нам нужно использовать this._m.value = 0 для установки значения поля m . В общем, при просмотре свойств объектов необходимо будет использовать .value для доступа к значениям, на которые ссылаются эти поля.

Завершите упрощенный код

Но в вашем случае вы можете упростить все, просто используя локальную переменную:

 Java.perform(function () {
    var SignUpActivity = Java.use('com.app.features.authentication.SignUpActivity');
    SignUpActivity.validatePhoneNumber.implementation = function() {
        
        const Carrier = Java.use("com.app.Carrier");
        const c = Carrier.$new();
        c.setId(123);
        this._carrier.value = c;
    };
});