Primitive types
How to use, intercept and modify primitive types with Frida
**** NOTE: BLOG MOVED TO https://cmrodriguez.me/ ****
In Java we have the following basic:
byte: Byte-length integer
short: Short integer
int: Integer
long: Long integer
float: Single-precision floating point
double: Double-precision floating point
char: A single character
boolean: A Boolean value (true or false)
Using integer types
The different integer types are casted by frida automatically to the Javascript numeric type, which is capable of holding the the long Java type without loosing information.
As an example the following code calls different functions from the BasicTypes class, and they are printed by Frida with no need to cast the types:
console.log is the function used to print in the frida CLI application output.
BasicTypes is the javascript wrapper for the BasicTypes class, binded by using the Java.use function.
Frida casts automatically values as well in the reimplementation of functions:
In this case to test the function, it needs to be run from the Java environment, because the changes are not being reflected on the method in the Frida environment, that is why I created in a button in the Main Activity of the application. So in order to trigger the modified behavior you need to click the button in the application.
Using boolean types
Frida converts automatically from Java boolean type to javascript boolean with no weird behavior. The following example is used to send boolean values from the Frida bridge to Java, and from Java to the script:
Using floating point types
In floating points we see some differences. The issue comes from the use of float values
As an example, when the 23/3 is executed, the Java operation returns 7.666666507720947, because of the limitation on the precision. But javascript by default has an extended precision, so the division returns 7.666666666666667, as the double Java operation does. So be careful when you override a method as there could be issues when some value is sent to a function that works on floats. The following code shows multiple scenarios of float manipulation:
which returns the following output:
javascript values
23/3: 7.666666666666667
0.1234567890123/1: 0.1234567890123
2/5: 0.4
java values
23/3 (float): 7.666666507720947
0.1234567890123/1 (float): 0.12345679104328156
2/5(float): 0.4
23/3 (double): 7.666666666666667
0.1234567890123/1 (double): 0.1234567890123
Using char types
Frida converts automatically from Java char type to javascript char with no weird behavior. The following example is used to send char values from the Frida bridge to Java, and from Java to the script:
Using String type
In this case the String is managed as a classic Java Object with some particularities regarding the javascript string type. Based on the previous logic used to send basic type parameters , we could call a method that receives two Strings in the following way:
When we run this, we get the following error:
This is an error because the parameter sent is a native javascript String, but it should be encapsulated in a java.lang.String object. So we need to create an instance of the String:
The second step to test is the override of a method that receives one or more String. We created the following function that overrides the concatString method from the example APK:
This code works perfectly because Frida wraps the String parameters and then returns a Javascript String to the internal implementation. So the concatenation works as in javascript, and Frida is in charge of converting the result to a java.lang.String object. Also the concatenation works with native attributes as it does in Java. As an example the following command works in java and in Javascript in the same way:
String comparison
The difference between a comparison between a native variable and a String is that the former is an object. So the variable that the developer manipulates holds a reference (pointer or memory value) to the real object. This is the reason a comparison == does not work with Strings, as it will naturally compare the references from the two Strings instead of the content. So to compare in Frida you should use the following script:
Accesing String attributes
If the String is in an attribute of a class, and you want to get access from the Frida script, you need to access it through the attribute "value", as in the following example:
Encapsulation of attributes (optional)
Initially I thought the access to an attribute will be transparent for the frida cli, so the first time I got to the situation of retrieving it, I tested the following FridaSnippet:
which printed "Direct access: [object Object]". This is due to the fact that the attributes in a Frida Object holds an encapsulation of a class. So when someone access it directly, it will return this content, and in this case it will cast it to the default Object string. To print the raw content of the variable (to check what it is), we can use the JSON.stringify javascript function:
which will return:
which shows that the field is of type java.lang.String. In order to return the actual value, we should call the attribute value from the Frida Object.
Last updated