I have an app I want to analyze with Frida. The app has over 20 different shared preferences XML files. I am hooking the put methods of the shared preferences like in this code snippet:
var sp = Java.use("android.app.SharedPreferencesImpl$EditorImpl");
sp.putString.implementation = function(var0, var1) {
console.log(var0 + " " + var1 + "\n");
return this.putString(var0, var1);
}
This class has no method like getPath() or similar. How can I add code into this hooked method, to receive the correct xml file? When I use getSharedPreferences from android.content.ContextWrapper it does not work, because the app uses so many xml files that I can not tell, where the written info belongs to.
I tried out to hook variables and methods from SharedPreferencesImpl. I tried to get the mfile which is an java.io.File object, but I could not make it to call the getPath() method from the file object. I also tried to hook several methods in SharedPreferencesImpl but it does not work. I am also not sure if this is the right way.
You can simply get the file name where the string is written to is applied on this way:
var sp = Java.use("android.app.SharedPreferencesImpl$EditorImpl");
sp.putString.implementation = function (key, value) {
console.log(`putString("${key}", "${value}")`);
let outer = this.this$0.value; // SharedPreferencesImpl
console.log("pref file: " + outer.mFile.value);
return this.putString(key, value);
}
android.app.SharedPreferencesImpl$EditorImpl
is a non-static inner class of android.app.SharedPreferencesImpl
. This means that every $EditorImpl
instance has a reference to it's outer class SharedPreferencesImpl
.
You won't see this field in the source code of those classes as it is an implicit reference generated by the compiler. So when the Java code is compiled the compiler adds a parameter to all constructors of the inner class and generates to save this value in a special field in the inner class.
You can get a list of all fields of EditorImpl
in the frida console by executing the following two commands:
var sp = Java.use("android.app.SharedPreferencesImpl$EditorImpl");
sp.class.getDeclaredFields().forEach(f => console.log(f))
You will get a list of fields, including this one:
final android.app.SharedPreferencesImpl android.app.SharedPreferencesImpl$EditorImpl.this$0
So we now know the field name of the outer class is this$0
- if we are in the Frida hooking code of putString
we can get the outer class by reading this.this$0.value
.
From here to the value of mFile
, where the File
is stored in we are interested in, it is just a small step:
this.this$0.value.mFile.value;