-
-
Save FrankSpierings/6e2608e22121b1aeaaa4588f13387dde to your computer and use it in GitHub Desktop.
function getGenericInterceptor(className, func, parameters) { | |
args = [] | |
for (i = 0; i < parameters.length; i++) { | |
args.push('arg_' + i) | |
} | |
var script = "result = this.__FUNCNAME__(__SEPARATED_ARG_NAMES__);\nlogmessage = '__CLASSNAME__.__FUNCNAME__(' + __SEPARATED_ARG_NAMES__ + ') => ' + result;\nconsole.log(logmessage);\nreturn result;" | |
script = script.replace(/__FUNCNAME__/g, func); | |
script = script.replace(/__SEPARATED_ARG_NAMES__/g, args.join(', ')); | |
script = script.replace(/__CLASSNAME__/g, className); | |
script = script.replace(/\+ \+/g, '+'); | |
args.push(script) | |
cb = Function.apply(null, args) | |
return cb | |
} | |
function hookall(className, func, cb) { | |
const clazz = Java.use(className); | |
overloads = clazz[func].overloads; | |
for (i in overloads) { | |
if (overloads[i].hasOwnProperty('argumentTypes')) { | |
var parameters = []; | |
for (j in overloads[i].argumentTypes) { | |
parameters.push(overloads[i].argumentTypes[j].className); | |
} | |
const cb = getGenericInterceptor(className, func, parameters); | |
clazz[func].overload.apply('this', parameters).implementation = cb; | |
} | |
} | |
} | |
if (Java.available) { | |
// Switch to the Java context | |
Java.perform(function() { | |
const JavaString = Java.use('java.lang.String'); | |
//Hook all init overloads | |
hookall('java.lang.StringBuilder', '$init', 'a'); | |
}) | |
} |
The last bit of the code I mentioned shows you how to obtain the overloads.
// Give this function the overloads array and it will return their signature.
function getOverloads(overloads) {
var results = []
for (i in overloads) {
if (overloads[i].hasOwnProperty('argumentTypes')) {
var parameters = []
for (j in overloads[i].argumentTypes) {
parameters.push("'" + overloads[i].argumentTypes[j].className + "'")
}
}
// results.push(overloads[i].name + '(' + parameters.join(', ') + ')')
results.push('.overload(' + parameters.join(', ') + ')')
}
return results.join('\n')
}
Overriding the specific implementation
of an overload should create the hook for only that version of the method. I have been out of the Frida stuff for quite some time, so I can't code it by heart (or give you exact coding advice).
@wving5 Ok I got it, big thanks. So...... It does have some property after all...
overloads[0].argumentTypes
But what kind of type is on overloads array inside? How can I know about overload prototype or some documentation? I did not find anything about this types in Java \ JavaScript docs....
Can you, maybe, share some link to read about this weird types, because if I know about this property on a overload object I would implement this in 5 min after I need this :) But the real issue was I din't even know what kind of the type has overload(s)
...
So I would appreciate to get some link about this kind of types, I assume those are internal Frida types or something, I'm right?
I believe the overloads array is created by Frida around here; https://github.com/frida/frida-java-bridge/blob/1443e3ef82e719de51c8eb586c27882f98bbf0c5/lib/class-factory.js#L331. It uses Java's introspection from JNI to populate this information. The Java types that are used are based on this: https://docs.oracle.com/javase/6/docs/technotes/guides/jni/spec/types.html#wp16432.
@wving5 Thanks for the info. Really helpful.
Here we go, created method that searches for a specific class.method
signature, maybe some one will need something like me so you will find it here :)
function getSpecificMethodOverload(methodFullName, args) {
var delimiter = methodFullName.lastIndexOf('.');
if (delimiter === -1) throw new Error('methodFullName is invalid');
var targetClass = methodFullName.slice(0, delimiter);
var targetMethod = methodFullName.slice(delimiter + 1, methodFullName.length);
var clazz = Java.use(targetClass);
if (!args) return null;
if (args.length === 0) return clazz[targetMethod].overload();
return clazz[targetMethod].overloads.find(overload => {
if (overload.argumentTypes && overload.argumentTypes.length === args.length) {
var argsFromOverload = overload.argumentTypes.map(argType => argType.className);
return JSON.stringify(argsFromOverload) === JSON.stringify(args)
}
});
}
// Usage:
var specificOverload = getSpecificMethodOverload('com.appname.classname.methodname', ['java.lang.Boolean', 'java.lang.String']);
P.S. There are many other stuff btw, you can search for an methods with specific modifier [public, private, etc..] or even method return value type.
Anyway tnx for help once again, have a nice life :)
@wving5 I guess I didn't explain well :)
I have class with some method which has about 40+ overloads, and I dont need to trace all of them I want to trace only one specific overload of the method with signature
Java.use(targetClass)[targetMethod].overload('java.lang.String', 'java.lang.String')
- Only trace one overload that receives two input arguments String and String, and do not trace rest overloads.And I can't understand how to find one specific overload in the .overloads array, I tried code I posted above but it doesn't work, seems like it wants directly define like
var specificOverload = Java.use(targetClass)[targetMethod].overload('java.lang.String', 'java.lang.String');
- This one works, but I want to set the signatures dynamically, this is the issue actually...