152 lines
4.9 KiB
JavaScript
152 lines
4.9 KiB
JavaScript
// $ frida -Uf com.whatsapp --no-pause -l wa.js
|
|
/*
|
|
#!/bin/bash
|
|
for fgbg in 38 48 ; do # Foreground / Background
|
|
for color in {0..255} ; do # Colors
|
|
# Display the color
|
|
printf "\e[${fgbg};5;%sm %3s \e[0m" $color $color
|
|
# Display 6 colors per lines
|
|
if [ $((($color + 1) % 6)) == 4 ] ; then
|
|
echo # New line
|
|
fi
|
|
done
|
|
echo # New line
|
|
done
|
|
*/
|
|
var Color = {
|
|
RESET: "\x1b[39;49;00m", Black: "0;01", Blue: "4;01", Cyan: "6;01", Gray: "7;11", Green: "2;01", Purple: "5;01", Red: "1;01", Yellow: "3;01",
|
|
Light: {
|
|
Black: "0;11", Blue: "4;11", Cyan: "6;11", Gray: "7;01", Green: "2;11", Purple: "5;11", Red: "1;11", Yellow: "3;11"
|
|
}
|
|
};
|
|
|
|
/**
|
|
*
|
|
* @param input.
|
|
* If an object is passed it will print as json
|
|
* @param kwargs options map {
|
|
* -l level: string; log/warn/error
|
|
* -i indent: boolean; print JSON prettify
|
|
* -c color: @see ColorMap
|
|
* }
|
|
*/
|
|
var LOG = function (input, kwargs) {
|
|
kwargs = kwargs || {};
|
|
var logLevel = kwargs['l'] || 'log', colorPrefix = '\x1b[3', colorSuffix = 'm';
|
|
if (typeof input === 'object')
|
|
input = JSON.stringify(input, null, kwargs['i'] ? 2 : null);
|
|
if (kwargs['c'])
|
|
input = colorPrefix + kwargs['c'] + colorSuffix + input + Color.RESET;
|
|
console[logLevel](input);
|
|
};
|
|
|
|
var printBacktrace = function () {
|
|
Java.perform(function() {
|
|
var android_util_Log = Java.use('android.util.Log'), java_lang_Exception = Java.use('java.lang.Exception');
|
|
// getting stacktrace by throwing an exception
|
|
LOG(android_util_Log.getStackTraceString(java_lang_Exception.$new()), { c: Color.Gray });
|
|
});
|
|
};
|
|
|
|
function traceClass(targetClass) {
|
|
var hook;
|
|
try {
|
|
hook = Java.use(targetClass);
|
|
} catch (e) {
|
|
console.error("trace class failed", e);
|
|
return;
|
|
}
|
|
|
|
var methods = hook.class.getDeclaredMethods();
|
|
hook.$dispose();
|
|
|
|
var parsedMethods = [];
|
|
methods.forEach(function (method) {
|
|
var methodStr = method.toString();
|
|
var methodReplace = methodStr.replace(targetClass + ".", "TOKEN").match(/\sTOKEN(.*)\(/)[1];
|
|
parsedMethods.push(methodReplace);
|
|
});
|
|
|
|
uniqBy(parsedMethods, JSON.stringify).forEach(function (targetMethod) {
|
|
traceMethod(targetClass + '.' + targetMethod);
|
|
});
|
|
}
|
|
|
|
function traceMethod(targetClassMethod) {
|
|
var delim = targetClassMethod.lastIndexOf('.');
|
|
if (delim === -1)
|
|
return;
|
|
|
|
var targetClass = targetClassMethod.slice(0, delim);
|
|
var targetMethod = targetClassMethod.slice(delim + 1, targetClassMethod.length);
|
|
|
|
var hook = Java.use(targetClass);
|
|
var overloadCount = hook[targetMethod].overloads.length;
|
|
|
|
LOG({ tracing: targetClassMethod, overloaded: overloadCount }, { c: Color.Green });
|
|
|
|
for (var i = 0; i < overloadCount; i++) {
|
|
hook[targetMethod].overloads[i].implementation = function () {
|
|
var log = { '#': targetClassMethod, args: [] };
|
|
|
|
for (var j = 0; j < arguments.length; j++) {
|
|
var arg = arguments[j];
|
|
// quick&dirty fix for java.io.StringWriter char[].toString() impl because frida prints [object Object]
|
|
if (j === 0 && arguments[j]) {
|
|
if (arguments[j].toString() === '[object Object]') {
|
|
var s = [];
|
|
for (var k = 0, l = arguments[j].length; k < l; k++) {
|
|
s.push(arguments[j][k]);
|
|
}
|
|
arg = s.join('');
|
|
}
|
|
}
|
|
log.args.push({ i: j, o: arg, s: arg ? arg.toString(): 'null'});
|
|
}
|
|
|
|
var retval;
|
|
try {
|
|
retval = this[targetMethod].apply(this, arguments); // might crash (Frida bug?)
|
|
log.returns = { val: retval, str: retval ? retval.toString() : null };
|
|
} catch (e) {
|
|
console.error(e);
|
|
}
|
|
LOG(log, { c: Color.Blue });
|
|
return retval;
|
|
}
|
|
}
|
|
}
|
|
|
|
// remove duplicates from array
|
|
function uniqBy(array, key) {
|
|
var seen = {};
|
|
return array.filter(function (item) {
|
|
var k = key(item);
|
|
return seen.hasOwnProperty(k) ? false : (seen[k] = true);
|
|
});
|
|
}
|
|
|
|
|
|
var Main = function() {
|
|
Java.perform(function () { // avoid java.lang.ClassNotFoundException
|
|
[
|
|
// "java.io.File",
|
|
'java.net.Socket'
|
|
].forEach(traceClass);
|
|
|
|
Java.use('java.net.Socket').isConnected.overload().implementation = function () {
|
|
LOG('Socket.isConnected.overload', { c: Color.Light.Cyan });
|
|
printBacktrace();
|
|
return true;
|
|
}
|
|
});
|
|
};
|
|
|
|
Java.perform(Main);
|
|
|
|
// setTimeout(function () {
|
|
// LOG('\n\t1. WiFi ON\n\t2. Wait for "Restore backup"\n\t3. WiFi OFF\n\t4. Main()\n\t5. Click RESTORE\n',
|
|
// { color: ColorMap.Black });
|
|
// }, 0);
|
|
|