rms-runtime-mobile-security
Version:
Runtime Mobile Security (RMS), powered by FRIDA, is a powerful web interface that helps you to manipulate Android and iOS Apps at Runtime
135 lines (119 loc) • 4.33 kB
JavaScript
/****************************************************************************************************************************
* Name: PBEKeySpec tracer
* OS: Android
* Author: FSecureLABS
* Source: https://github.com/FSecureLABS/android-keystore-audit/blob/master/frida-scripts/tracer-secretkeyfactory.js
* Info:
PBEKeySpec tracer allows to see parameters (including password) from which PBKDF keys are generated
*****************************************************************************************************************************/
Java.perform(function () {
//hookSecretKeyFactory_getInstance();
hookPBEKeySpec();
hookPBEKeySpec2();
hookPBEKeySpec3();
});
send("SecretKeyFactory hooks loaded!");
var cipherList = [];
var StringCls = null;
Java.perform(function () {
StringCls = Java.use('java.lang.String');
});
function hookSecretKeyFactory_getInstance()
{
var func = Java.use('javax.crypto.SecretKeyFactory')['getInstance'];
func.implementation = function(flag) {
send("[SecretKeyFactory.getInstance()]: flag: " + flag );
return this.getInstance(flag);
}
}
/*
.overload('[C')
.overload('[C', '[B', 'int')
.overload('[C', '[B', 'int', 'int')
*/
function hookPBEKeySpec()
{
var PBEKeySpec = Java.use('javax.crypto.spec.PBEKeySpec')['$init'].overload('[C');
PBEKeySpec.implementation = function(pass) {
send("[PBEKeySpec.PBEKeySpec()]: pass: " + charArrayToString(pass) );
return this.$init(pass);
}
}
function hookPBEKeySpec2()
{
var PBEKeySpec = Java.use('javax.crypto.spec.PBEKeySpec')['$init'].overload('[C', '[B', 'int');
PBEKeySpec.implementation = function(pass, salt, iter) {
send("[PBEKeySpec.PBEKeySpec2()]: pass: " + charArrayToString(pass) + " iter: "+iter);
dumpByteArray("salt",salt)
return this.$init(pass,salt,iter);
}
}
function hookPBEKeySpec3()
{
var PBEKeySpec = Java.use('javax.crypto.spec.PBEKeySpec')['$init'].overload('[C', '[B', 'int', 'int');
PBEKeySpec.implementation = function(pass, salt, iter, keyLength) {
send("[PBEKeySpec.PBEKeySpec3()]: pass: " + charArrayToString(pass) + " iter: "+iter + " keyLength: "+keyLength);
dumpByteArray("salt",salt)
return this.$init(pass,salt,iter,keyLength);
}
}
function charArrayToString(charArray)
{
if(charArray == null)
return '(null)';
else
return StringCls.$new(charArray);
}
function dumpByteArray(title,byteArr)
{
if(byteArr!=null)
{
try{
var buff = new ArrayBuffer(byteArr.length)
var dtv = new DataView(buff)
for(var i = 0; i < byteArr.length; i++){
dtv.setUint8(i,byteArr[i]); // Frida sucks sometimes and returns different byteArr.length between ArrayBuffer(byteArr.length) and for(..; i < byteArr.length;..). It occured even when Array.copyOf was done to work on copy.
}
send( title+":\n");
send(hexdumpJS(dtv.buffer,0,byteArr.length))
} catch(error){send("Exception has occured in hexdump")}
}
else
{
send("byteArr is null!");
}
}
function _fillUp (value, count, fillWith) {
var l = count - value.length;
var ret = "";
while (--l > -1)
ret += fillWith;
return ret + value;
}
function hexdumpJS (arrayBuffer, offset, length) {
var view = new DataView(arrayBuffer);
offset = offset || 0;
length = length || arrayBuffer.byteLength;
var out = _fillUp("Offset", 8, " ") + " 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F\n";
var row = "";
for (var i = 0; i < length; i += 16) {
row += _fillUp(offset.toString(16).toUpperCase(), 8, "0") + " ";
var n = Math.min(16, length - offset);
var string = "";
for (var j = 0; j < 16; ++j) {
if (j < n) {
var value = view.getUint8(offset);
string += (value >= 32 && value < 128) ? String.fromCharCode(value) : ".";
row += _fillUp(value.toString(16).toUpperCase(), 2, "0") + " ";
offset++;
}
else {
row += " ";
string += " ";
}
}
row += " " + string + "\n";
}
out += row;
return out;
};