mirror of
https://github.com/androguard/androguard.git
synced 2024-11-26 22:40:33 +00:00
Fix crypto js and add the automatic tracing in the db
This commit is contained in:
parent
f8daa928e3
commit
fca5f2eff5
@ -1,8 +1,8 @@
|
||||
// Ripped from https://github.com/Ch0pin/medusa/ and modified to fit Androguard packets
|
||||
|
||||
console.log('[+] LOADING INTERNAL/UTILS.JS');
|
||||
console.log("[+] LOADING INTERNAL/UTILS.JS");
|
||||
|
||||
'use strict';
|
||||
("use strict");
|
||||
|
||||
var FLAG_SECURE_VALUE = "";
|
||||
var mode = "";
|
||||
@ -12,7 +12,7 @@ var requestBody = "";
|
||||
var responseHeaders = "";
|
||||
var responseBody = "";
|
||||
|
||||
const java_lang_threadObj = Java.use('java.lang.Thread').$new();
|
||||
const java_lang_threadObj = Java.use("java.lang.Thread").$new();
|
||||
|
||||
function getStackTrace() {
|
||||
const stack = java_lang_threadObj.currentThread().getStackTrace();
|
||||
@ -33,8 +33,8 @@ function flatten(obj) {
|
||||
}
|
||||
|
||||
const Packet = {
|
||||
id: 'AG-EVENT',
|
||||
payload: '',
|
||||
id: "AG-EVENT",
|
||||
payload: "",
|
||||
|
||||
toString() {
|
||||
return JSON.stringify(flatten(this));
|
||||
@ -84,26 +84,26 @@ function agBinderPacket(source, payload) {
|
||||
}
|
||||
|
||||
function dumpIntent(intent) {
|
||||
var cmp = ""
|
||||
var cmp = "";
|
||||
if (intent.getComponent()) {
|
||||
cmp = intent.getComponent().getClassName()
|
||||
cmp = intent.getComponent().getClassName();
|
||||
}
|
||||
|
||||
return {action: intent.getAction(), cmp: cmp, flags: intent.getFlags()}
|
||||
return { action: intent.getAction(), cmp: cmp, flags: intent.getFlags() };
|
||||
}
|
||||
|
||||
function dumpReceiver(receiver) {
|
||||
if (receiver != null) {
|
||||
return { name: receiver.getClass().toString() }
|
||||
return { name: receiver.getClass().toString() };
|
||||
}
|
||||
|
||||
return {}
|
||||
return {};
|
||||
}
|
||||
|
||||
function dumpFilter(filter) {
|
||||
if (filter != null) {
|
||||
actions_list = []
|
||||
categories_list = []
|
||||
actions_list = [];
|
||||
categories_list = [];
|
||||
|
||||
for (iAction = 0; iAction < filter.countActions(); iAction++) {
|
||||
actions_list.push(filter.getAction(iAction));
|
||||
@ -113,75 +113,94 @@ function dumpFilter(filter) {
|
||||
categories_list.push(filter.getCategory(iCategory));
|
||||
}
|
||||
|
||||
return {actions: actions_list, categories: categories_list}
|
||||
return { actions: actions_list, categories: categories_list };
|
||||
}
|
||||
|
||||
return {}
|
||||
return {};
|
||||
}
|
||||
|
||||
function dumpWebview(wv) {
|
||||
return {
|
||||
getAllowContentAccess: wv.getSettings().getAllowContentAccess(), getJavaScriptEnabled: wv.getSettings().getJavaScriptEnabled(), getAllowFileAccess: wv.getSettings().getAllowFileAccess(),
|
||||
getAllowFileAccessFromFileURLs: wv.getSettings().getAllowFileAccessFromFileURLs(), getAllowUniversalAccessFromFileURLs: wv.getSettings().getAllowUniversalAccessFromFileURLs()
|
||||
}
|
||||
getAllowContentAccess: wv.getSettings().getAllowContentAccess(),
|
||||
getJavaScriptEnabled: wv.getSettings().getJavaScriptEnabled(),
|
||||
getAllowFileAccess: wv.getSettings().getAllowFileAccess(),
|
||||
getAllowFileAccessFromFileURLs: wv
|
||||
.getSettings()
|
||||
.getAllowFileAccessFromFileURLs(),
|
||||
getAllowUniversalAccessFromFileURLs: wv
|
||||
.getSettings()
|
||||
.getAllowUniversalAccessFromFileURLs(),
|
||||
};
|
||||
}
|
||||
|
||||
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",
|
||||
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"
|
||||
}
|
||||
Black: "0;11",
|
||||
Blue: "4;11",
|
||||
Cyan: "6;11",
|
||||
Gray: "7;01",
|
||||
Green: "2;11",
|
||||
Purple: "5;11",
|
||||
Red: "1;11",
|
||||
Yellow: "3;11",
|
||||
},
|
||||
};
|
||||
|
||||
function enumerateModules() {
|
||||
|
||||
var modules = Process.enumerateModules();
|
||||
colorLog('[+] Enumerating loaded modules:',{c: Color.Blue});
|
||||
colorLog("[+] Enumerating loaded modules:", { c: Color.Blue });
|
||||
|
||||
for (var i = 0; i < modules.length; i++)
|
||||
console.log(modules[i].path + modules[i].name);
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
function getApplicationContext() {
|
||||
return Java.use('android.app.ActivityThread').currentApplication().getApplicationContext();
|
||||
return Java.use("android.app.ActivityThread")
|
||||
.currentApplication()
|
||||
.getApplicationContext();
|
||||
}
|
||||
|
||||
function traceClass(targetClass)
|
||||
{
|
||||
|
||||
console.log("entering traceClass")
|
||||
function traceClass(targetClass) {
|
||||
colorLog("[+] entering traceClass", { c: Color.Red });
|
||||
|
||||
var hook = Java.use(targetClass);
|
||||
var methods = hook.class.getDeclaredMethods();
|
||||
hook.$dispose();
|
||||
|
||||
console.log("entering pasedMethods")
|
||||
colorLog("[+] entering parsedMethods", { c: Color.Blue });
|
||||
|
||||
var parsedMethods = [];
|
||||
methods.forEach(function (method) {
|
||||
try {
|
||||
parsedMethods.push(method.toString().replace(targetClass + ".", "TOKEN").match(/\sTOKEN(.*)\(/)[1]);
|
||||
}
|
||||
catch(err){}
|
||||
parsedMethods.push(
|
||||
method
|
||||
.toString()
|
||||
.replace(targetClass + ".", "TOKEN")
|
||||
.match(/\sTOKEN(.*)\(/)[1],
|
||||
);
|
||||
} catch (err) {}
|
||||
});
|
||||
|
||||
console.log("entering traceMethods")
|
||||
|
||||
colorLog("[+] entering traceMethods", { c: Color.Blue });
|
||||
|
||||
var targets = uniqBy(parsedMethods, JSON.stringify);
|
||||
targets.forEach(function (targetMethod) {
|
||||
try {
|
||||
traceMethod(targetClass + "." + targetMethod);
|
||||
}
|
||||
catch(err){}
|
||||
} catch (err) {}
|
||||
});
|
||||
}
|
||||
|
||||
function uniqBy(array, key)
|
||||
{
|
||||
function uniqBy(array, key) {
|
||||
var seen = {};
|
||||
return array.filter(function (item) {
|
||||
var k = key(item);
|
||||
@ -189,38 +208,42 @@ function uniqBy(array, key)
|
||||
});
|
||||
}
|
||||
|
||||
function traceMethod(targetClassMethod)
|
||||
{
|
||||
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 targetClass = targetClassMethod.slice(0, delim);
|
||||
var targetMethod = targetClassMethod.slice(
|
||||
delim + 1,
|
||||
targetClassMethod.length,
|
||||
);
|
||||
|
||||
var hook = Java.use(targetClass);
|
||||
var overloadCount = hook[targetMethod].overloads.length;
|
||||
|
||||
colorLog("Tracing " + targetClassMethod + " [" + overloadCount + " overload(s)]",{c: Color.Green});
|
||||
colorLog(
|
||||
"Tracing " + targetClassMethod + " [" + overloadCount + " overload(s)]",
|
||||
{ c: Color.Green },
|
||||
);
|
||||
|
||||
for (var i = 0; i < overloadCount; i++) {
|
||||
|
||||
hook[targetMethod].overloads[i].implementation = function () {
|
||||
colorLog("\n[+] Entering: " + targetClassMethod,{c: Color.Red});
|
||||
colorLog("\n[+] Entering: " + targetClassMethod, {
|
||||
c: Color.Yellow,
|
||||
});
|
||||
|
||||
if (arguments.length) console.log();
|
||||
for (var j = 0; j < arguments.length; j++) {
|
||||
console.log("\targ[" + j + "]: " + arguments[j]);
|
||||
agPacket({ arg: arguments[j] }).send();
|
||||
}
|
||||
|
||||
// print retval
|
||||
var retval = this[targetMethod].apply(this, arguments); // rare crash (Frida bug?)
|
||||
console.log("\n\tRetval: " + retval);
|
||||
var retval = this[targetMethod].apply(this, arguments);
|
||||
agPacket({ ret: retval }).send();
|
||||
colorLog("\n[-] Exiting " + targetClassMethod);
|
||||
return retval;
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
var Utf8 = {
|
||||
encode: function (string) {
|
||||
@ -230,12 +253,10 @@ var Utf8 = {
|
||||
var c = string.charCodeAt(n);
|
||||
if (c < 128) {
|
||||
utftext += String.fromCharCode(c);
|
||||
}
|
||||
else if((c > 127) && (c < 2048)) {
|
||||
} else if (c > 127 && c < 2048) {
|
||||
utftext += String.fromCharCode((c >> 6) | 192);
|
||||
utftext += String.fromCharCode((c & 63) | 128);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
utftext += String.fromCharCode((c >> 12) | 224);
|
||||
utftext += String.fromCharCode(((c >> 6) & 63) | 128);
|
||||
utftext += String.fromCharCode((c & 63) | 128);
|
||||
@ -247,51 +268,63 @@ var Utf8 = {
|
||||
decode: function (utftext) {
|
||||
var string = "";
|
||||
var i = 0;
|
||||
var c = c1 = c2 = 0;
|
||||
var c = (c1 = c2 = 0);
|
||||
while (i < utftext.length) {
|
||||
c = utftext.charCodeAt(i);
|
||||
if (c < 128) {
|
||||
string += String.fromCharCode(c);
|
||||
i++;
|
||||
}
|
||||
else if((c > 191) && (c < 224)) {
|
||||
} else if (c > 191 && c < 224) {
|
||||
c2 = utftext.charCodeAt(i + 1);
|
||||
string += String.fromCharCode(((c & 31) << 6) | (c2 & 63));
|
||||
i += 2;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
c2 = utftext.charCodeAt(i + 1);
|
||||
c3 = utftext.charCodeAt(i + 2);
|
||||
string += String.fromCharCode(((c & 15) << 12) | ((c2 & 63) << 6) | (c3 & 63));
|
||||
string += String.fromCharCode(
|
||||
((c & 15) << 12) | ((c2 & 63) << 6) | (c3 & 63),
|
||||
);
|
||||
i += 3;
|
||||
}
|
||||
}
|
||||
return string;
|
||||
}
|
||||
}
|
||||
|
||||
},
|
||||
};
|
||||
|
||||
function describeJavaClass(className) {
|
||||
var jClass = Java.use(className);
|
||||
console.log(JSON.stringify({
|
||||
console.log(
|
||||
JSON.stringify(
|
||||
{
|
||||
_name: className,
|
||||
_methods: Object.getOwnPropertyNames(jClass.__proto__).filter(function(m) {
|
||||
return !m.startsWith('$') // filter out Frida related special properties
|
||||
|| m == 'class' || m == 'constructor' // optional
|
||||
}),
|
||||
_methods: Object.getOwnPropertyNames(jClass.__proto__).filter(
|
||||
function (m) {
|
||||
return (
|
||||
!m.startsWith("$") || // filter out Frida related special properties
|
||||
m == "class" ||
|
||||
m == "constructor"
|
||||
); // optional
|
||||
},
|
||||
),
|
||||
_fields: jClass.class.getFields().map(function (f) {
|
||||
return f.toString()
|
||||
})
|
||||
}, null, 2));
|
||||
return f.toString();
|
||||
}),
|
||||
},
|
||||
null,
|
||||
2,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
var colorLog = 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;
|
||||
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);
|
||||
};
|
||||
|
||||
@ -310,19 +343,22 @@ var processArgs = function(command, envp, dir) {
|
||||
// output.dir = dir;
|
||||
}
|
||||
// return output;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
var _byteArraytoHexString = function (byteArray) {
|
||||
if (!byteArray) { return 'null'; }
|
||||
if (!byteArray) {
|
||||
return "null";
|
||||
}
|
||||
if (byteArray.map) {
|
||||
return byteArray.map(function(byte) {
|
||||
return ('0' + (byte & 0xFF).toString(16)).slice(-2);
|
||||
}).join('');
|
||||
return byteArray
|
||||
.map(function (byte) {
|
||||
return ("0" + (byte & 0xff).toString(16)).slice(-2);
|
||||
})
|
||||
.join("");
|
||||
} else {
|
||||
return byteArray + "";
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
var updateInput = function (input) {
|
||||
if (input.length && input.length > 0) {
|
||||
@ -333,42 +369,41 @@ var _byteArraytoHexString = function(byteArray) {
|
||||
var normalized = input.toString();
|
||||
}
|
||||
return normalized;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
var byteArraytoHexString = function (byteArray) {
|
||||
if (byteArray && byteArray.map) {
|
||||
return byteArray.map(function(byte) {
|
||||
return ('0' + (byte & 0xFF).toString(16)).slice(-2);
|
||||
}).join('')
|
||||
return byteArray
|
||||
.map(function (byte) {
|
||||
return ("0" + (byte & 0xff).toString(16)).slice(-2);
|
||||
})
|
||||
.join("");
|
||||
} else {
|
||||
return JSON.stringify(byteArray);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
var hexToAscii = function (input) {
|
||||
var hex = input.toString();
|
||||
var str = '';
|
||||
var str = "";
|
||||
for (var i = 0; i < hex.length; i += 2)
|
||||
str += String.fromCharCode(parseInt(hex.substr(i, 2), 16));
|
||||
return str;
|
||||
}
|
||||
};
|
||||
|
||||
var displayString = function (input) {
|
||||
var str = input.replace('[','');
|
||||
var str1 = str.replace(']','');
|
||||
var res = str1.split(',');
|
||||
var ret = '';
|
||||
var str = input.replace("[", "");
|
||||
var str1 = str.replace("]", "");
|
||||
var res = str1.split(",");
|
||||
var ret = "";
|
||||
for (var i = 0; i < res.length; i++) {
|
||||
if(res[i] > 31 && res[i]<127)
|
||||
ret += String.fromCharCode(res[i]);
|
||||
else ret += ' ';
|
||||
|
||||
if (res[i] > 31 && res[i] < 127) ret += String.fromCharCode(res[i]);
|
||||
else ret += " ";
|
||||
}
|
||||
|
||||
colorLog("[+] PARSING TO STRING: " + ret, { c: Color.Green });
|
||||
colorLog('',{c:Color.RESET});
|
||||
}
|
||||
colorLog("", { c: Color.RESET });
|
||||
};
|
||||
var normalize = function (input) {
|
||||
if (input.length && input.length > 0) {
|
||||
var normalized = byteArraytoHexString(input);
|
||||
@ -378,7 +413,7 @@ var normalize = function(input) {
|
||||
var normalized = input.toString();
|
||||
}
|
||||
return normalized;
|
||||
}
|
||||
};
|
||||
|
||||
var normalizeInput = function (input) {
|
||||
if (input.array) {
|
||||
@ -389,7 +424,7 @@ var normalizeInput = function(input) {
|
||||
var normalized = JSON.stringify(input);
|
||||
}
|
||||
return normalized;
|
||||
}
|
||||
};
|
||||
|
||||
var getMode = function (Cipher, mode) {
|
||||
if (mode === 2) {
|
||||
@ -398,79 +433,81 @@ var getMode = function(Cipher, mode) {
|
||||
mode = "ENCRYPT";
|
||||
}
|
||||
return mode;
|
||||
}
|
||||
};
|
||||
|
||||
var getRandomValue = function (arg) {
|
||||
if (!arg) { return 'null'; }
|
||||
var type = arg.toString().split('@')[0].split('.');
|
||||
if (!arg) {
|
||||
return "null";
|
||||
}
|
||||
var type = arg.toString().split("@")[0].split(".");
|
||||
type = type[type.length - 1];
|
||||
if (type === "SecureRandom") {
|
||||
if (arg.getSeed) {
|
||||
return byteArraytoHexString(arg.getSeed(10));
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
var normalizeKey = function (cert_or_key) {
|
||||
var type = cert_or_key.toString().split('@')[0].split('.');
|
||||
var type = cert_or_key.toString().split("@")[0].split(".");
|
||||
type = type[type.length - 1];
|
||||
if (type === "SecretKeySpec") {
|
||||
return byteArraytoHexString(cert_or_key.getEncoded());
|
||||
} else {
|
||||
return "non-SecretKeySpec: " + cert_or_key.toString() + ", encoded: " + byteArraytoHexString(cert_or_key.getEncoded()) + ", object: " + JSON.stringify(cert_or_key);
|
||||
}
|
||||
|
||||
return (
|
||||
"non-SecretKeySpec: " +
|
||||
cert_or_key.toString() +
|
||||
", encoded: " +
|
||||
byteArraytoHexString(cert_or_key.getEncoded()) +
|
||||
", object: " +
|
||||
JSON.stringify(cert_or_key)
|
||||
);
|
||||
}
|
||||
};
|
||||
var byteArrayToString = function (input) {
|
||||
var buffer = Java.array('byte', input);
|
||||
var buffer = Java.array("byte", input);
|
||||
|
||||
var result = "";
|
||||
|
||||
for (var i = 0; i < buffer.length; i++) {
|
||||
if (buffer[i] > 31 && buffer[i] < 127) {
|
||||
result += (String.fromCharCode(buffer[i]));
|
||||
}
|
||||
else {
|
||||
result += ' ';
|
||||
result += String.fromCharCode(buffer[i]);
|
||||
} else {
|
||||
result += " ";
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
};
|
||||
|
||||
var byteArrayToStringE = function (input) {
|
||||
var buffer = Java.array('byte', input);
|
||||
var buffer = Java.array("byte", input);
|
||||
var result = "";
|
||||
var unprintable = false;
|
||||
for (var i = 0; i < buffer.length; ++i) {
|
||||
if (buffer[i] > 31 && buffer[i] < 127)
|
||||
result+= (String.fromCharCode(buffer[i]));
|
||||
result += String.fromCharCode(buffer[i]);
|
||||
else {
|
||||
unprintable = true;
|
||||
result = "Input cant be transformed to ascii string";
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
function readStreamToHex(stream) {
|
||||
var data = [];
|
||||
var byteRead = stream.read();
|
||||
while (byteRead != -1)
|
||||
{
|
||||
data.push( ('0' + (byteRead & 0xFF).toString(16)).slice(-2) );
|
||||
while (byteRead != -1) {
|
||||
data.push(("0" + (byteRead & 0xff).toString(16)).slice(-2));
|
||||
/* <---------------- binary to hex ---------------> */
|
||||
byteRead = stream.read();
|
||||
}
|
||||
stream.close();
|
||||
return data.join('');
|
||||
return data.join("");
|
||||
}
|
||||
|
||||
|
||||
|
||||
const jni_struct_array = [
|
||||
"reserved0",
|
||||
"reserved1",
|
||||
@ -704,35 +741,33 @@ const jni_struct_array = [
|
||||
"NewDirectByteBuffer",
|
||||
"GetDirectBufferAddress",
|
||||
"GetDirectBufferCapacity",
|
||||
"GetObjectRefType"
|
||||
]
|
||||
"GetObjectRefType",
|
||||
];
|
||||
|
||||
/*
|
||||
Calculate the given funcName address from the JNIEnv pointer
|
||||
*/
|
||||
function getJNIFunctionAdress(jnienv_addr, func_name) {
|
||||
var offset = jni_struct_array.indexOf(func_name) * Process.pointerSize
|
||||
var offset = jni_struct_array.indexOf(func_name) * Process.pointerSize;
|
||||
|
||||
// console.log("offset : 0x" + offset.toString(16))
|
||||
|
||||
return Memory.readPointer(jnienv_addr.add(offset))
|
||||
return Memory.readPointer(jnienv_addr.add(offset));
|
||||
}
|
||||
|
||||
|
||||
// Hook all function to have an overview of the function called
|
||||
function hook_all(jnienv_addr) {
|
||||
jni_struct_array.forEach(function (func_name) {
|
||||
// Calculating the address of the function
|
||||
if(!func_name.includes("reserved"))
|
||||
{
|
||||
var func_addr = getJNIFunctionAdress(jnienv_addr,func_name)
|
||||
if (!func_name.includes("reserved")) {
|
||||
var func_addr = getJNIFunctionAdress(jnienv_addr, func_name);
|
||||
Interceptor.attach(func_addr, {
|
||||
onEnter: function (args) {
|
||||
console.log("[+] Entered : " + func_name)
|
||||
console.log("[+] Entered : " + func_name);
|
||||
},
|
||||
});
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
function inspectObject(obj) {
|
||||
@ -742,15 +777,16 @@ function inspectObject(obj) {
|
||||
const fields = obj_class.getDeclaredFields();
|
||||
const methods = obj_class.getMethods();
|
||||
console.log("Inspecting " + obj.getClass().toString());
|
||||
console.log("[+]------------------------------Fields------------------------------:");
|
||||
for (var i in fields)
|
||||
console.log("\t\t" + fields[i].toString());
|
||||
console.log("[+]------------------------------Methods-----------------------------:");
|
||||
for (var i in methods)
|
||||
console.log("\t\t" + methods[i].toString());
|
||||
console.log(
|
||||
"[+]------------------------------Fields------------------------------:",
|
||||
);
|
||||
for (var i in fields) console.log("\t\t" + fields[i].toString());
|
||||
console.log(
|
||||
"[+]------------------------------Methods-----------------------------:",
|
||||
);
|
||||
for (var i in methods) console.log("\t\t" + methods[i].toString());
|
||||
}
|
||||
|
||||
|
||||
//------------------------https://github.com/CreditTone/hooker----------------------------
|
||||
|
||||
function classExists(className) {
|
||||
@ -762,7 +798,7 @@ function classExists(className) {
|
||||
//console.log(err);
|
||||
}
|
||||
return exists;
|
||||
};
|
||||
}
|
||||
|
||||
function methodInBeat(invokeId, timestamp, methodName, executor) {
|
||||
var startTime = timestamp;
|
||||
@ -771,16 +807,32 @@ var startTime = timestamp;
|
||||
var threadClz = Java.use("java.lang.Thread");
|
||||
var currentThread = threadClz.currentThread();
|
||||
var stackInfo = androidLogClz.getStackTraceString(exceptionClz.$new());
|
||||
var str = ("------------startFlag:" + invokeId + ",objectHash:"+executor+",thread(id:" + currentThread.getId() +",name:" + currentThread.getName() + "),timestamp:" + startTime+"---------------\n");
|
||||
var str =
|
||||
"------------startFlag:" +
|
||||
invokeId +
|
||||
",objectHash:" +
|
||||
executor +
|
||||
",thread(id:" +
|
||||
currentThread.getId() +
|
||||
",name:" +
|
||||
currentThread.getName() +
|
||||
"),timestamp:" +
|
||||
startTime +
|
||||
"---------------\n";
|
||||
str += methodName + "\n";
|
||||
str += stackInfo.substring(20);
|
||||
str += ("------------endFlag:" + invokeId + ",usedtime:" + (new Date().getTime() - startTime) +"---------------\n");
|
||||
str +=
|
||||
"------------endFlag:" +
|
||||
invokeId +
|
||||
",usedtime:" +
|
||||
(new Date().getTime() - startTime) +
|
||||
"---------------\n";
|
||||
console.log(str);
|
||||
};
|
||||
}
|
||||
|
||||
function log(str) {
|
||||
console.log(str);
|
||||
};
|
||||
}
|
||||
|
||||
function tryGetClass(className) {
|
||||
var clz = undefined;
|
||||
@ -790,9 +842,9 @@ function tryGetClass(className) {
|
||||
return clz;
|
||||
}
|
||||
|
||||
var containRegExps = new Array()
|
||||
var containRegExps = new Array();
|
||||
|
||||
var notContainRegExps = new Array(RegExp(/\.jpg/), RegExp(/\.png/))
|
||||
var notContainRegExps = new Array(RegExp(/\.jpg/), RegExp(/\.png/));
|
||||
|
||||
function check(str) {
|
||||
str = str.toString();
|
||||
@ -814,18 +866,24 @@ function check(str) {
|
||||
//------------------------https://github.com/CreditTone/hooker EOF----------------------------
|
||||
|
||||
function sendAppInfo() {
|
||||
var context = null
|
||||
var ActivityThread = Java.use('android.app.ActivityThread');
|
||||
var context = null;
|
||||
var ActivityThread = Java.use("android.app.ActivityThread");
|
||||
var app = ActivityThread.currentApplication();
|
||||
|
||||
if (app != null) {
|
||||
context = app.getApplicationContext();
|
||||
var app_classname = app.getClass().toString().split(' ')[1];
|
||||
var app_classname = app.getClass().toString().split(" ")[1];
|
||||
|
||||
var filesDirectory = context.getFilesDir().getAbsolutePath().toString();
|
||||
var cacheDirectory = context.getCacheDir().getAbsolutePath().toString();
|
||||
var externalCacheDirectory= context.getExternalCacheDir().getAbsolutePath().toString();
|
||||
var codeCacheDirectory= 'getCodeCacheDir' in context ? context.getCodeCacheDir().getAbsolutePath().toString() : 'N/A';
|
||||
var externalCacheDirectory = context
|
||||
.getExternalCacheDir()
|
||||
.getAbsolutePath()
|
||||
.toString();
|
||||
var codeCacheDirectory =
|
||||
"getCodeCacheDir" in context
|
||||
? context.getCodeCacheDir().getAbsolutePath().toString()
|
||||
: "N/A";
|
||||
var obbDir = context.getObbDir().getAbsolutePath().toString();
|
||||
var packageCodePath = context.getPackageCodePath().toString();
|
||||
var applicationName = app_classname;
|
||||
@ -840,22 +898,23 @@ function sendAppInfo(){
|
||||
info.packageCodePath = packageCodePath;
|
||||
|
||||
agSysPacket({ information: "app", info: info }).send();
|
||||
|
||||
} else {
|
||||
console.log("No context yet!")
|
||||
console.log("No context yet!");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//------------------------https://github.com/CreditTone/hooker EOF----------------------------
|
||||
|
||||
function notifyNewSharedPreference(key, value) {
|
||||
var k = key;
|
||||
var v = value;
|
||||
Java.use('android.app.SharedPreferencesImpl$EditorImpl').putString.overload('java.lang.String', 'java.lang.String').implementation = function(k, v) {
|
||||
console.log('[SharedPreferencesImpl]', k, '=', v);
|
||||
Java.use("android.app.SharedPreferencesImpl$EditorImpl").putString.overload(
|
||||
"java.lang.String",
|
||||
"java.lang.String",
|
||||
).implementation = function (k, v) {
|
||||
console.log("[SharedPreferencesImpl]", k, "=", v);
|
||||
return this.putString(k, v);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
// Send some stuff about the app
|
||||
|
@ -1,86 +1,142 @@
|
||||
// Ripped from https://github.com/Ch0pin/medusa/ and modified to fit Androguard packets
|
||||
|
||||
colorLog('[+] LOADING ENCRYPTION/CIPHER.JS', {c: Color.Red});
|
||||
colorLog("[+] LOADING ENCRYPTION/CIPHER.JS", { c: Color.Red });
|
||||
|
||||
var cipher = Java.use('javax.crypto.Cipher');
|
||||
var cipher = Java.use("javax.crypto.Cipher");
|
||||
|
||||
|
||||
|
||||
cipher.init.overload('int', 'java.security.Key').implementation = function(mode, key) {
|
||||
var operation = '';
|
||||
cipher.init.overload("int", "java.security.Key").implementation = function (
|
||||
mode,
|
||||
key,
|
||||
) {
|
||||
var operation = "";
|
||||
var algorithm = this.getAlgorithm();
|
||||
|
||||
if(mode == 1)
|
||||
operation = "Encrypting";
|
||||
else if(mode == 2)
|
||||
operation = "Decrypting";
|
||||
if (mode == 1) operation = "Encrypting";
|
||||
else if (mode == 2) operation = "Decrypting";
|
||||
|
||||
agPacket({algorithm: algorithm, operation: operation, mode: mode, key: byteArraytoHexString(key.getEncoded())}).send();
|
||||
agPacket({
|
||||
algorithm: algorithm,
|
||||
operation: operation,
|
||||
mode: mode,
|
||||
key: byteArraytoHexString(key.getEncoded()),
|
||||
}).send();
|
||||
|
||||
return this.init(mode, key);
|
||||
}
|
||||
};
|
||||
|
||||
cipher.init.overload('int', 'java.security.Key', 'java.security.spec.AlgorithmParameterSpec').implementation = function(mode, key, paramsec) {
|
||||
var operation = '';
|
||||
cipher.init.overload(
|
||||
"int",
|
||||
"java.security.Key",
|
||||
"java.security.spec.AlgorithmParameterSpec",
|
||||
).implementation = function (mode, key, paramsec) {
|
||||
var operation = "";
|
||||
var algorithm = this.getAlgorithm();
|
||||
var castedToIv = Java.cast(paramsec, Java.use('javax.crypto.spec.IvParameterSpec'));
|
||||
|
||||
if(mode == 1)
|
||||
operation = "Encrypting";
|
||||
else if(mode == 2)
|
||||
operation = "Decrypting";
|
||||
if (mode == 1) operation = "Encrypting";
|
||||
else if (mode == 2) operation = "Decrypting";
|
||||
|
||||
agPacket({
|
||||
algorithm: algorithm,
|
||||
mode: mode,
|
||||
operation: operation,
|
||||
key: byteArraytoHexString(key.getEncoded()),
|
||||
iv: paramsec,
|
||||
}).send();
|
||||
|
||||
agPacket({algorithm: algorithm, mode: mode, operation: operation, key: byteArraytoHexString(key.getEncoded()), iv: byteArraytoHexString(castedToIv.getIV())}).send();
|
||||
return this.init(mode, key, paramsec);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
cipher.init.overload('int', 'java.security.Key', 'java.security.AlgorithmParameters', 'java.security.SecureRandom').implementation = function(mode, key, paramsec, secRnd){
|
||||
var operation = '';
|
||||
cipher.init.overload(
|
||||
"int",
|
||||
"java.security.Key",
|
||||
"java.security.AlgorithmParameters",
|
||||
"java.security.SecureRandom",
|
||||
).implementation = function (mode, key, paramsec, secRnd) {
|
||||
var operation = "";
|
||||
var algorithm = this.getAlgorithm();
|
||||
var castedToIv = Java.cast(paramsec, Java.use('javax.crypto.spec.IvParameterSpec'));
|
||||
|
||||
if(mode == 1)
|
||||
operation = "Encrypting";
|
||||
else if(mode == 2)
|
||||
operation = "Decrypting";
|
||||
if (mode == 1) operation = "Encrypting";
|
||||
else if (mode == 2) operation = "Decrypting";
|
||||
|
||||
agPacket({algorithm: algorithm, mode: mode, operation: operation, key: byteArraytoHexString(key.getEncoded()), iv: byteArraytoHexString(castedToIv.getIV())}).send();
|
||||
agPacket({
|
||||
algorithm: algorithm,
|
||||
mode: mode,
|
||||
operation: operation,
|
||||
key: byteArraytoHexString(key.getEncoded()),
|
||||
iv: paramsec,
|
||||
secRnd: secRnd,
|
||||
}).send();
|
||||
return this.init(mode, key, paramsec, secRnd);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
//DO FINAL--------------------------------
|
||||
|
||||
cipher.doFinal.overload('[B').implementation = function(byteArray) {
|
||||
cipher.doFinal.overload("[B").implementation = function (byteArray) {
|
||||
var ret = this.doFinal(byteArray);
|
||||
agPacket({in: byteArray, ret: ret}).send();
|
||||
agPacket({
|
||||
in: byteArraytoHexString(byteArray),
|
||||
ret: byteArraytoHexString(ret),
|
||||
}).send();
|
||||
return ret;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
cipher.doFinal.overload('[B', 'int').implementation = function(byteArray, outputOffset) {
|
||||
cipher.doFinal.overload("[B", "int").implementation = function (
|
||||
byteArray,
|
||||
outputOffset,
|
||||
) {
|
||||
var ret = this.doFinal(byteArray, outputOffset);
|
||||
agPacket({ in: byteArray, outputOffset: outputOffset, ret: ret }).send();
|
||||
return ret;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
cipher.doFinal.overload('[B', 'int', 'int').implementation = function(byteArray, outputOffset, inputlen) {
|
||||
cipher.doFinal.overload("[B", "int", "int").implementation = function (
|
||||
byteArray,
|
||||
outputOffset,
|
||||
inputlen,
|
||||
) {
|
||||
var ret = this.doFinal(byteArray, outputOffset, inputlen);
|
||||
agPacket({in: byteArray, outputOffset: outputOffset, inputlen: inputlen, ret: ret}).send();
|
||||
agPacket({
|
||||
in: byteArray,
|
||||
outputOffset: outputOffset,
|
||||
inputlen: inputlen,
|
||||
ret: ret,
|
||||
}).send();
|
||||
return ret;
|
||||
}
|
||||
};
|
||||
|
||||
cipher.doFinal.overload('[B', 'int', 'int', '[B').implementation = function(byteArray, outputOffset, inputlen, output) {
|
||||
cipher.doFinal.overload("[B", "int", "int", "[B").implementation = function (
|
||||
byteArray,
|
||||
outputOffset,
|
||||
inputlen,
|
||||
output,
|
||||
) {
|
||||
var ret = this.doFinal(byteArray, outputOffset, inputlen, output);
|
||||
agPacket({in: byteArray, out: output, outputOffset: outputOffset, inputlen: inputlen, ret: ret}).send();
|
||||
agPacket({
|
||||
in: byteArray,
|
||||
out: output,
|
||||
outputOffset: outputOffset,
|
||||
inputlen: inputlen,
|
||||
ret: ret,
|
||||
}).send();
|
||||
return ret;
|
||||
}
|
||||
};
|
||||
|
||||
cipher.doFinal.overload('[B', 'int', 'int', '[B', 'int').implementation = function(byteArray, outputOffset, inputlen, output, outoffset) {
|
||||
var ret = this.doFinal(byteArray, outputOffset ,inputlen, output, outoffset);
|
||||
agPacket({in: byteArray, out: output, outputOffset: outputOffset, inputlen: inputlen, outoffset: outoffset, ret: ret}).send();
|
||||
cipher.doFinal.overload("[B", "int", "int", "[B", "int").implementation =
|
||||
function (byteArray, outputOffset, inputlen, output, outoffset) {
|
||||
var ret = this.doFinal(
|
||||
byteArray,
|
||||
outputOffset,
|
||||
inputlen,
|
||||
output,
|
||||
outoffset,
|
||||
);
|
||||
agPacket({
|
||||
in: byteArray,
|
||||
out: output,
|
||||
outputOffset: outputOffset,
|
||||
inputlen: inputlen,
|
||||
outoffset: outoffset,
|
||||
ret: ret,
|
||||
}).send();
|
||||
return ret;
|
||||
}
|
||||
};
|
||||
|
57
androguard/pentest/modules/encryption/keystore.js
Normal file
57
androguard/pentest/modules/encryption/keystore.js
Normal file
@ -0,0 +1,57 @@
|
||||
// Ripped from https://github.com/Ch0pin/medusa/ and modified to fit Androguard packets
|
||||
|
||||
colorLog("[+] LOADING ENCRYPTION/KEYSTORE.JS", { c: Color.Red });
|
||||
|
||||
var keystore = Java.use("java.security.KeyStore");
|
||||
|
||||
keystore.containsAlias.overload("java.lang.String").implementation = function (
|
||||
alias,
|
||||
) {
|
||||
var ret = this.containsAlias(alias);
|
||||
agPacket({
|
||||
alias: alias,
|
||||
ret: ret,
|
||||
}).send();
|
||||
|
||||
return ret;
|
||||
};
|
||||
|
||||
keystore.getKey.overload("java.lang.String", "[C").implementation = function (
|
||||
alias,
|
||||
password,
|
||||
) {
|
||||
var ret = this.getKey(alias, password);
|
||||
agPacket({
|
||||
alias: alias,
|
||||
password: password,
|
||||
algorithm: ret.getAlgorithm(),
|
||||
encoded: ret.getEncoded(),
|
||||
ret: ret,
|
||||
}).send();
|
||||
|
||||
return ret;
|
||||
};
|
||||
|
||||
keystore.load.overload("java.io.InputStream", "[C").implementation = function (
|
||||
stream,
|
||||
charArray,
|
||||
) {
|
||||
/* sometimes this happen, I have no idea why, tho... */
|
||||
if (stream == null) {
|
||||
/* just to avoid interfering with app's flow */
|
||||
this.load(stream, charArray);
|
||||
return;
|
||||
}
|
||||
|
||||
var hexString = readStreamToHex(stream);
|
||||
|
||||
agPacket({
|
||||
certType: this.getType(),
|
||||
password: charArray,
|
||||
cert: hexString,
|
||||
}).send();
|
||||
|
||||
/* call the original implementation of 'load' */
|
||||
this.load(stream, charArray);
|
||||
/* no need to return anything */
|
||||
};
|
14
androguard/pentest/modules/preferences/preferences.js
Normal file
14
androguard/pentest/modules/preferences/preferences.js
Normal file
@ -0,0 +1,14 @@
|
||||
// Ripped from https://github.com/Ch0pin/medusa/ and modified to fit Androguard packets
|
||||
|
||||
colorLog("[+] LOADING PREFERENCES/PREFERENCES.JS", { c: Color.Red });
|
||||
|
||||
var ContextWrapper = Java.use("android.content.ContextWrapper");
|
||||
|
||||
ContextWrapper.getSharedPreferences.overload(
|
||||
"java.lang.String",
|
||||
"int",
|
||||
).implementation = function (var0, var1) {
|
||||
var sharedPreferences = this.getSharedPreferences(var0, var1);
|
||||
agPacket({ name: var0, mode: var1, ret: sharedPreferences }).send();
|
||||
return sharedPreferences;
|
||||
};
|
Loading…
Reference in New Issue
Block a user