Closed 4val0v closed 4 years ago
1) Because of this problem, hooking does not work (Only methods with Object) !
2) For the void
methods you do not need to generate out
!
Hey @4val0v can you kindly share the APK? Many thanks
Hi @m0bilesecurity! No difference what will it be application
Here look:
Hook lab -> generated code: | wrong | fixed |
---|---|---|
char[] |
[C |
|
java.lang.Object[] |
[Ljava.lang.Object; |
|
java.lang.String[][] |
[[Ljava.lang.String; |
|
java.lang.Long[][] |
[[Ljava.lang.Long; |
|
java.lang.String[][][][] |
[[[[Ljava.lang.String; |
I'll leave it here, suddenly someone will be interested: https://stackoverflow.com/a/19098229/3469132
@m0bilesecurity Run the generated code using frida to see the error
frida -U --no-pause -f com.wtf.myapplication -l test.js
Hey @4val0v, many thanks for all the precious info provided. The issue is clear, notation for overloading methods with an array as arg is in smali. So according to this table:
Element Type Encoding
boolean Z
byte B
char C
class or interface Lclassname;
double D
float F
int I
long J
short S
we need to adjust the laodmethod in default.js in order to convert arrays in the right notation. Does exist something ready to use?
@m0bilesecurity Java - Frida methods: https://neo-geo2.gitbook.io/adventures-on-security/frida-scripting-guide/methods | Java | Frida |
---|---|---|
int |
int |
|
byte |
byte |
|
short |
short |
|
long |
long |
|
float |
float |
|
double |
double |
|
char |
char |
|
<Object> (eg. String) |
<package>.<Object> (eg. java.lang.String) |
|
int[] |
[I |
|
byte[] |
[B |
|
short[] |
[S |
|
long[] |
[J |
|
float[] |
[F |
|
double[] |
[D |
|
char[] |
[C |
|
<Object>[] |
[L<package>.<Object> (eg. [Ljava.lang.String) |
https://android.googlesource.com/platform/dalvik/+/gingerbread/docs/dex-format.html
@m0bilesecurity If you have time, you can continue...
Java.perform(function() {
var targetClass = Java.use("com.wtf.myapplication.MainActivity");
var currentMethods = targetClass.class.getDeclaredMethods(); // all methods declared in a Java Class
console.log("Count methods for class: " + currentMethods.length);
for (var i = 0; i < currentMethods.length; i++) {
var args = currentMethods[i].toString().split('(')[1].split(')')[0].split(',');
console.log("\nCurrent method: " + currentMethods[i].getName());
console.log("args: " + args);
// TODO for i
};
});
Take a look here: https://juejin.im/post/5e967cb5f265da47a74134a6#heading-9 (It didn't work for me)
Please check this quick and dirty solution.
// check if the current arg is an array
var arg = args_array[i]
if(arg.includes("[]")){
// arg is an array --> smali notation conversion
if (arg.includes(".")) arg="L"+arg+";"
else if((/boolean/i).test(arg)) arg="Z"+arg.replace(/boolean/i, "");
else if((/byte/i).test(arg)) arg="B"+arg.replace(/byte/i, "");
else if((/char/i).test(arg)) arg="C"+arg.replace(/char/i, "");
else if((/double/i).test(arg)) arg="D"+arg.replace(/double/i, "");
else if((/float/i).test(arg)) arg="F"+arg.replace(/float/i, "");
else if((/int/i).test(arg)) arg="I"+arg.replace(/int/i, "");
else if((/long/i).test(arg)) arg="J"+arg.replace(/long/i, "");
else if((/short/i).test(arg)) arg="S"+arg.replace(/short/i, "");
else arg="L"+arg+";"
}
while(arg.includes("[]")){
arg=arg.replace("[]", "")
arg="["+arg
}
Some tests are needed. If you want to help me, just replace the loadmethods function inside default.js with the code below:
loadmethods: function (loaded_classes) {
var loaded_methods = {};
Java.perform(function () {
loaded_classes.forEach(function (className, index) {
var jClass;
var classMethods_dirty;
//catch possible issues
try{
jClass = Java.use(className);
classMethods_dirty = jClass.class.getDeclaredMethods();
}catch(err){
send("Exception while loading methods for "+className);
//skip current loop
loaded_methods[className] = []
return;
}
var classMethods = []
classMethods_dirty.forEach(function (m) {
var method_and_args = {};
//Cleaning up
m = m.toString();
//add info for the UI
method_and_args["ui_name"] = m.replace(className + ".", "")
// Remove generics from the method
while (m.includes("<")) {
m = m.replace(/<.*?>/g, "");
}
// remove "Throws"
if (m.indexOf(" throws ") !== -1) {
m = m.substring(0, m.indexOf(" throws "));
}
// remove scope and return type declarations
m = m.slice(m.lastIndexOf(" "));
// remove the class name
m = m.replace(className + ".", "");
// remove the signature (args)
method_and_args["name"] = m.split("(")[0].trim()
// get the args
var args_dirty = ((/\((.*?)\)/.exec(m)[1]).trim())
// add quotes between every arg
var args_array = args_dirty.split(",")
var args_srt = ""
for (var i = 0; i < args_array.length; i++) {
// check if the current arg is an array
var arg = args_array[i]
if(arg.includes("[]")){
// arg is an array --> smali notation conversion
if (arg.includes(".")) arg="L"+arg+";"
else if((/boolean/i).test(arg)) arg="Z"+arg.replace(/boolean/i, "");
else if((/byte/i).test(arg)) arg="B"+arg.replace(/byte/i, "");
else if((/char/i).test(arg)) arg="C"+arg.replace(/char/i, "");
else if((/double/i).test(arg)) arg="D"+arg.replace(/double/i, "");
else if((/float/i).test(arg)) arg="F"+arg.replace(/float/i, "");
else if((/int/i).test(arg)) arg="I"+arg.replace(/int/i, "");
else if((/long/i).test(arg)) arg="J"+arg.replace(/long/i, "");
else if((/short/i).test(arg)) arg="S"+arg.replace(/short/i, "");
else arg="L"+arg+";"
}
while(arg.includes("[]")){
arg=arg.replace("[]", "")
arg="["+arg
}
args_srt = args_srt + ("\"" + arg + "\"")
//add a comma if the current item is not the last one
if (i + 1 < args_array.length) args_srt = args_srt + ",";
}
method_and_args["args"] = args_srt
classMethods.push(method_and_args);
});
loaded_methods[className] = classMethods;
});
})
//DEBUG console.log("loaded_classes.length: " + loaded_classes.length)
//DEBUG console.log("loaded_methods.length: " + Object.keys(loaded_methods).length)
return loaded_methods;
},
@4val0v can you kindly add a button to your test app in order to call the "test" method?
@m0bilesecurity Now everything is OK !
Still need fixed a functional on page "Dump TAB" -> "Hook all methods"
FIXED 🚀! Check the last commit. I prefer to keep the signature of the method without the smali notation because it's more easy to read.
Under the hood, the hook is managed correctly also in the dump page ;) I tested your sample app and now I'm able to hook the "test" method. Many thanks for the detailed info provided! Best Paolo
Describe the bug: Incorrect parameters generation for method overloading !
Steps to reproduce: Custom Logging Implementation: (See methods)
Go to "hook lab", select a Logging class: (highlighted) Generated:
java.lang.Object[]
[Ljava.lang.Object;
Desktop:
Smartphone: