搜集部分脚本
This commit is contained in:
commit
9cade69ab9
14
code/GPS欺骗.js
Normal file
14
code/GPS欺骗.js
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
const lat = 27.9864882;
|
||||||
|
const lng = 33.7279001;
|
||||||
|
|
||||||
|
Java.perform(function () {
|
||||||
|
var Location = Java.use("android.location.Location");
|
||||||
|
Location.getLatitude.implementation = function() {
|
||||||
|
send("Overwriting Lat to " + lat);
|
||||||
|
return lat;
|
||||||
|
}
|
||||||
|
Location.getLongitude.implementation = function() {
|
||||||
|
send("Overwriting Lng to " + lng);
|
||||||
|
return lng;
|
||||||
|
}
|
||||||
|
})
|
40
code/InMemoryDexClassLoader dump.js
Normal file
40
code/InMemoryDexClassLoader dump.js
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
console.log("[*] In Memory Dex Dump v0.1 - @cryptax");
|
||||||
|
|
||||||
|
Java.perform(function() {
|
||||||
|
var memoryclassLoader = Java.use("dalvik.system.InMemoryDexClassLoader");
|
||||||
|
memoryclassLoader.$init.overload('java.nio.ByteBuffer', 'java.lang.ClassLoader').implementation = function(dexbuffer, loader) {
|
||||||
|
console.log("[*] Hooking InMemoryDexClassLoader");
|
||||||
|
var object = this.$init(dexbuffer, loader);
|
||||||
|
|
||||||
|
/* dexbuffer is a Java ByteBuffer
|
||||||
|
you cannot dump to /sdcard unless the app has rights to
|
||||||
|
*/
|
||||||
|
var remaining = dexbuffer.remaining();
|
||||||
|
const filename = '/data/data/YOUR-PACKAGE-NAME/dump.dex';
|
||||||
|
|
||||||
|
console.log("[*] Opening file name=" + filename + " to write " + remaining + " bytes");
|
||||||
|
const f = new File(filename, 'wb');
|
||||||
|
var buf = new Uint8Array(remaining);
|
||||||
|
for (var i = 0; i < remaining; i++) {
|
||||||
|
buf[i] = dexbuffer.get();
|
||||||
|
//debug: console.log("buf["+i+"]="+buf[i]);
|
||||||
|
}
|
||||||
|
console.log("[*] Writing " + remaining + " bytes...");
|
||||||
|
f.write(buf);
|
||||||
|
f.close();
|
||||||
|
|
||||||
|
// checking
|
||||||
|
remaining = dexbuffer.remaining();
|
||||||
|
if (remaining > 0) {
|
||||||
|
console.log("[-] Error: There are " + remaining + " remaining bytes!");
|
||||||
|
} else {
|
||||||
|
console.log("[+] Dex dumped successfully in " + filename);
|
||||||
|
}
|
||||||
|
|
||||||
|
return object;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
});
|
46
code/Print Android Logs in console.js
Normal file
46
code/Print Android Logs in console.js
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
Java.perform(function() {
|
||||||
|
var Log = Java.use("android.util.Log");
|
||||||
|
Log.d.overload('java.lang.String', 'java.lang.String', 'java.lang.Throwable').implementation = function(a, b, c) {
|
||||||
|
console.log("The application reports Log.d(" + a.toString() + ", " + b.toString() + ")");
|
||||||
|
return this.d(a, b, c);
|
||||||
|
};
|
||||||
|
Log.v.overload('java.lang.String', 'java.lang.String', 'java.lang.Throwable').implementation = function(a, b, c) {
|
||||||
|
console.log("The application reports Log.v(" + a.toString() + ", " + b.toString() + ")");
|
||||||
|
return this.v(a, b, c);
|
||||||
|
};
|
||||||
|
|
||||||
|
Log.i.overload('java.lang.String', 'java.lang.String', 'java.lang.Throwable').implementation = function(a, b, c) {
|
||||||
|
console.log("The application reports Log.i(" + a.toString() + ", " + b.toString() + ")");
|
||||||
|
return this.i(a, b, c);
|
||||||
|
};
|
||||||
|
Log.e.overload('java.lang.String', 'java.lang.String', 'java.lang.Throwable').implementation = function(a, b, c) {
|
||||||
|
console.log("The application reports Log.e(" + a.toString() + ", " + b.toString() + ")");
|
||||||
|
return this.e(a, b, c);
|
||||||
|
};
|
||||||
|
Log.w.overload('java.lang.String', 'java.lang.String', 'java.lang.Throwable').implementation = function(a, b, c) {
|
||||||
|
console.log("The application reports Log.w(" + a.toString() + ", " + b.toString() + ")");
|
||||||
|
return this.w(a, b, c);
|
||||||
|
};
|
||||||
|
Log.d.overload('java.lang.String', 'java.lang.String').implementation = function(a, b) {
|
||||||
|
console.log("The application reports Log.d(" + a.toString() + ", " + b.toString() + ")");
|
||||||
|
return this.d(a, b);
|
||||||
|
};
|
||||||
|
Log.v.overload('java.lang.String', 'java.lang.String').implementation = function(a, b) {
|
||||||
|
console.log("The application reports Log.v(" + a.toString() + ", " + b.toString() + ")");
|
||||||
|
return this.v(a, b);
|
||||||
|
};
|
||||||
|
|
||||||
|
Log.i.overload('java.lang.String', 'java.lang.String').implementation = function(a, b) {
|
||||||
|
console.log("The application reports Log.i(" + a.toString() + ", " + b.toString() + ")");
|
||||||
|
return this.i(a, b);
|
||||||
|
};
|
||||||
|
Log.e.overload('java.lang.String', 'java.lang.String').implementation = function(a, b) {
|
||||||
|
console.log("The application reports Log.e(" + a.toString() + ", " + b.toString() + ")");
|
||||||
|
return this.e(a, b);
|
||||||
|
};
|
||||||
|
Log.w.overload('java.lang.String', 'java.lang.String').implementation = function(a, b) {
|
||||||
|
console.log("The application reports Log.w(" + a.toString() + ", " + b.toString() + ")");
|
||||||
|
return this.w(a, b);
|
||||||
|
};
|
||||||
|
|
||||||
|
});
|
156
code/SQLite数据库通用钩子.js
Normal file
156
code/SQLite数据库通用钩子.js
Normal file
@ -0,0 +1,156 @@
|
|||||||
|
/*
|
||||||
|
Author: secretdiary.ninja
|
||||||
|
License: (CC BY-SA 4.0)
|
||||||
|
* */
|
||||||
|
|
||||||
|
setImmediate(function() {
|
||||||
|
Java.perform(function() {
|
||||||
|
var sqliteDatabase = Java.use("android.database.sqlite.SQLiteDatabase");
|
||||||
|
|
||||||
|
// execSQL(String sql)
|
||||||
|
sqliteDatabase.execSQL.overload('java.lang.String').implementation = function(var0) {
|
||||||
|
console.log("[*] SQLiteDatabase.exeqSQL called with query: " + var0 + "\n");
|
||||||
|
var execSQLRes = this.execSQL(var0);
|
||||||
|
return execSQLRes;
|
||||||
|
};
|
||||||
|
|
||||||
|
// execSqL(String, sql, Obj[] bindArgs)
|
||||||
|
sqliteDatabase.execSQL.overload('java.lang.String', '[Ljava.lang.Object;').implementation = function(var0, var1) {
|
||||||
|
console.log("[*] SQLiteDatabase.exeqSQL called with query: " + var0 + " and arguments: " + var1 + "\n");
|
||||||
|
var execSQLRes = this.execSQL(var0, var1);
|
||||||
|
return execSQLRes;
|
||||||
|
};
|
||||||
|
|
||||||
|
// query(boolean distinct, String table, String[] columns, String selection, String[] selectionArgs, String groupBy, String having, String orderBy, String limit)
|
||||||
|
sqliteDatabase.query.overload('boolean', 'java.lang.String', '[Ljava.lang.String;', 'java.lang.String', '[Ljava.lang.String;', 'java.lang.String', 'java.lang.String', 'java.lang.String', 'java.lang.String').implementation = function(var0, var1, var2, var3, var4, var5, var6, var7, var8) {
|
||||||
|
var methodVal = "[*] SQLiteDatabase.query called.";
|
||||||
|
var logVal = "Table: " + var1 + ", selection value: " + var3 + ", selectionArgs: " + var4 + " distinct: " + var0;
|
||||||
|
console.log(methodVal + " " + logVal + "\n");
|
||||||
|
var queryRes = this.query(var0, var1, var2, var3, var4, var5, var6, var7, var8);
|
||||||
|
return queryRes;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// query(String table, String[] columns, String selection, String[] selectionArgs, String groupBy, String having, String orderBy, String limit)
|
||||||
|
sqliteDatabase.query.overload('java.lang.String', '[Ljava.lang.String;', 'java.lang.String', '[Ljava.lang.String;', 'java.lang.String', 'java.lang.String', 'java.lang.String', 'java.lang.String').implementation = function(var0, var1, var2, var3, var4, var5, var6, var7) {
|
||||||
|
var methodVal = "[*] SQLiteDatabase.query called.";
|
||||||
|
var logVal = "Table: " + var0 + ", selection value: " + var2 + ", selectionArgs: " + var3;
|
||||||
|
console.log(methodVal + " " + logVal + "\n");
|
||||||
|
var queryRes = this.query(var0, var1, var2, var3, var4, var5, var6, var7);
|
||||||
|
return queryRes;
|
||||||
|
};
|
||||||
|
|
||||||
|
// query(boolean distinct, String table, String[] columns, String selection, String[] selectionArgs, String groupBy, String having, String orderBy, String limit, CancellationSignal cancellationSignal)
|
||||||
|
sqliteDatabase.query.overload('boolean', 'java.lang.String', '[Ljava.lang.String;', 'java.lang.String', '[Ljava.lang.String;', 'java.lang.String', 'java.lang.String', 'java.lang.String', 'java.lang.String', 'android.os.CancellationSignal').implementation = function(var0, var1, var2, var3, var4, var5, var6, var7, var8, var9) {
|
||||||
|
var methodVal = "[*] SQLiteDatabase.query called.";
|
||||||
|
var logVal = "Table: " + var1 + ", selection value: " + var3 + ", selectionArgs: " + var4;
|
||||||
|
console.log(methodVal + " " + logVal + "\n");
|
||||||
|
var queryRes = this.query(var0, var1, var2, var3, var4, var5, var6, var7, var8, var9);
|
||||||
|
return queryRes;
|
||||||
|
};
|
||||||
|
|
||||||
|
// query(String table, String[] columns, String selection, String[] selectionArgs, String groupBy, String having, String orderBy)
|
||||||
|
sqliteDatabase.query.overload('java.lang.String', '[Ljava.lang.String;', 'java.lang.String', '[Ljava.lang.String;', 'java.lang.String', 'java.lang.String', 'java.lang.String').implementation = function(var0, var1, var2, var3, var4, var5, var6) {
|
||||||
|
var methodVal = "[*] SQLiteDatabase.query called.";
|
||||||
|
var logVal = "Table: " + var0 + ", selection value: " + var2 + ", selectionArgs: " + var3;
|
||||||
|
console.log(methodVal + " " + logVal + "\n");
|
||||||
|
var queryRes = this.query(var0, var1, var2, var3, var4, var5, var6);
|
||||||
|
return queryRes;
|
||||||
|
};
|
||||||
|
|
||||||
|
// queryWithFactory(SQLiteDatabase.CursorFactory cursorFactory, boolean distinct, String table, String[] columns, String selection, String[] selectionArgs, String groupBy, String having, String orderBy, String limit, CancellationSignal cancellationSignal)
|
||||||
|
sqliteDatabase.queryWithFactory.overload('android.database.sqlite.SQLiteDatabase$CursorFactory', 'boolean', 'java.lang.String', '[Ljava.lang.String;', 'java.lang.String', '[Ljava.lang.String;', 'java.lang.String', 'java.lang.String', 'java.lang.String', 'java.lang.String').implementation = function(var0, var1, var2, var3, var4, var5, var6, var7, var8, var9) {
|
||||||
|
var methodVal = "[*] SQLiteDatabase.queryWithFactory called.";
|
||||||
|
var logVal = "Table: " + var2 + ", selection value: " + var4 + ", selectionArgs: " + var5 + " distinct: " + var1;
|
||||||
|
console.log(methodVal + " " + logVal + "\n");
|
||||||
|
var queryWithFactoryRes = this.queryWithFactory(var0, var1, var2, var3, var4, var5, var6, var7, var8, var9);
|
||||||
|
return queryWithFactoryRes;
|
||||||
|
};
|
||||||
|
|
||||||
|
// queryWithFactory(SQLiteDatabase.CursorFactory cursorFactory, boolean distinct, String table, String[] columns, String selection, String[] selectionArgs, String groupBy, String having, String orderBy, String limit)
|
||||||
|
sqliteDatabase.queryWithFactory.overload('android.database.sqlite.SQLiteDatabase$CursorFactory', 'boolean', 'java.lang.String', '[Ljava.lang.String;', 'java.lang.String', '[Ljava.lang.String;', 'java.lang.String', 'java.lang.String', 'java.lang.String', 'java.lang.String', 'android.os.CancellationSignal').implementation = function(var0, var1, var2, var3, var4, var5, var6, var7, var8, var9, var10) {
|
||||||
|
var methodVal = "[*] SQLiteDatabase.queryWithFactory called.";
|
||||||
|
var logVal = "Table: " + var2 + ", selection value: " + var4 + ", selectionArgs: " + var5 + " distinct: " + var1;
|
||||||
|
console.log(methodVal + " " + logVal + "\n");
|
||||||
|
var queryWithFactoryRes = this.queryWithFactory(var0, var1, var2, var3, var4, var5, var6, var7, var8, var9, var10);
|
||||||
|
return queryWithFactoryRes;
|
||||||
|
};
|
||||||
|
|
||||||
|
// rawQuery(String sql, String[] selectionArgs)
|
||||||
|
sqliteDatabase.rawQuery.overload('java.lang.String', '[Ljava.lang.String;').implementation = function(var0, var1) {
|
||||||
|
console.log("[*] SQLiteDatabase.rawQuery called with query: " + var0 + " and contentValues: " + var1 +"\n");
|
||||||
|
var rawQueryRes = this.rawQuery(var0, var1);
|
||||||
|
return rawQueryRes;
|
||||||
|
};
|
||||||
|
|
||||||
|
// rawQuery(String sql, String[] selectionArgs, CancellationSignal cancellationSignal)
|
||||||
|
sqliteDatabase.rawQuery.overload('java.lang.String', '[Ljava.lang.String;', 'android.os.CancellationSignal').implementation = function(var0, var1, var2) {
|
||||||
|
console.log("[*] SQLiteDatabase.rawQuery called with query: " + var0 + " and contentValues: " + var1 +"\n");
|
||||||
|
var rawQueryRes = this.rawQuery(var0, var1, var2);
|
||||||
|
return rawQueryRes;
|
||||||
|
};
|
||||||
|
|
||||||
|
// rawQueryWithFactory(SQLiteDatabase.CursorFactory cursorFactory, String sql, String[] selectionArgs, String editTable, CancellationSignal cancellationSignal)
|
||||||
|
sqliteDatabase.rawQueryWithFactory.overload('android.database.sqlite.SQLiteDatabase$CursorFactory', 'java.lang.String', '[Ljava.lang.String;', 'java.lang.String', 'android.os.CancellationSignal').implementation = function(var0, var1, var2, var3, var4) {
|
||||||
|
console.log("[*] SQLiteDatabase.rawQueryWithFactory called with query: " + var1 + " and contentValues: " + var2 + "\n");
|
||||||
|
var rawQueryWithFactoryRes = this.rawQueryWithFactory(var0, var1, var2, var3, var4);
|
||||||
|
return rawQueryWithFactoryRes;
|
||||||
|
};
|
||||||
|
|
||||||
|
// rawQueryWithFactory(SQLiteDatabase.CursorFactory cursorFactory, String sql, String[] selectionArgs, String editTable)
|
||||||
|
sqliteDatabase.rawQueryWithFactory.overload('android.database.sqlite.SQLiteDatabase$CursorFactory', 'java.lang.String', '[Ljava.lang.String;', 'java.lang.String').implementation = function(var0, var1, var2, var3) {
|
||||||
|
console.log("[*] SQLiteDatabase.rawQueryWithFactory2 called with query: " + var1 + " and contentValues: " + var2 +"\n");
|
||||||
|
var rawQueryWithFactoryRes = this.rawQueryWithFactory(var0, var1, var2, var3);
|
||||||
|
return rawQueryWithFactoryRes;
|
||||||
|
};
|
||||||
|
|
||||||
|
// insert(String table, String nullColumnHack, ContentValues values)
|
||||||
|
sqliteDatabase.insert.overload('java.lang.String', 'java.lang.String', 'android.content.ContentValues').implementation = function(var0, var1, var2) {
|
||||||
|
console.log("[*] SQLiteDatabase.insert called. Adding new value: " + var2 + " to database: " + var0 + "\n");
|
||||||
|
var insertValueRes = this.insert(var0, var1, var2);
|
||||||
|
return insertValueRes;
|
||||||
|
};
|
||||||
|
|
||||||
|
// insertOrThrow(String table, String nullColumnHack, ContentValues values)
|
||||||
|
sqliteDatabase.insertOrThrow.overload('java.lang.String', 'java.lang.String', 'android.content.ContentValues').implementation = function(var0, var1, var2) {
|
||||||
|
console.log("[*] SQLiteDatabase.insertOrThrow called. Adding new value: " + var2 + " to database: " + var0 + "\n");
|
||||||
|
var insertValueRes = this.insertOrThrow(var0, var1, var2);
|
||||||
|
return insertValueRes;
|
||||||
|
};
|
||||||
|
|
||||||
|
// insertOrThrow(String table, String nullColumnHack, ContentValues values)
|
||||||
|
sqliteDatabase.insertOrThrow.overload('java.lang.String', 'java.lang.String', 'android.content.ContentValues').implementation = function(var0, var1, var2) {
|
||||||
|
console.log("[*] SQLiteDatabase.insertOrThrow called. Adding new value: " + var2 + " to database: " + var0 + "\n");
|
||||||
|
var insertValueRes = this.insertOrThrow(var0, var1, var2);
|
||||||
|
return insertValueRes;
|
||||||
|
};
|
||||||
|
|
||||||
|
// insertWithOnConflict(String table, String nullColumnHack, ContentValues initialValues, int conflictAlgorithm)
|
||||||
|
sqliteDatabase.insertWithOnConflict.overload('java.lang.String', 'java.lang.String', 'android.content.ContentValues', 'int').implementation = function(var0, var1, var2, var3) {
|
||||||
|
console.log("[*] SQLiteDatabase.insertWithOnConflict called. Adding new value: " + var2 + " to database: " + var0 + " and conflictAlgorithm: " + var3 + "\n");
|
||||||
|
var insertValueRes = this.insertWithOnConflict(var0, var1, var2, var3);
|
||||||
|
return insertValueRes;
|
||||||
|
};
|
||||||
|
|
||||||
|
// update(String table, ContentValues values, String whereClause, String[] whereArgs)
|
||||||
|
sqliteDatabase.update.overload('java.lang.String', 'android.content.ContentValues', 'java.lang.String', '[Ljava.lang.String;').implementation = function(var0, var1, var2, var3) {
|
||||||
|
var methodVal = "[*] SQLiteDatabase.update called.";
|
||||||
|
var logVal = "Update table: " + var0 + " with where clause: " + var2 + " whereArgs:" + var3.toString() + " and values to update: " + var1.toString() +"\n";
|
||||||
|
console.log(methodVal, logVal);
|
||||||
|
|
||||||
|
var updateRes = this.update(var0, var1, var2, var3);
|
||||||
|
return updateRes;
|
||||||
|
};
|
||||||
|
|
||||||
|
// updateWithOnConflict(String table, ContentValues values, String whereClause, String[] whereArgs, int conflictAlgorithm)
|
||||||
|
sqliteDatabase.updateWithOnConflict.overload('java.lang.String', 'android.content.ContentValues', 'java.lang.String', '[Ljava.lang.String;', 'int').implementation = function(var0, var1, var2, var3, var4) {
|
||||||
|
var methodVal = "[*] SQLiteDatabase.updateWithOnConflict called.";
|
||||||
|
var logVal = "Update table: " + var0 + " with where clause: " + var2 + " whereArgs:" + var3 + " values to update: " + var1 + " and conflictAlgorithm: " + var4 +"\n";
|
||||||
|
console.log(methodVal, logVal);
|
||||||
|
|
||||||
|
var updateRes = this.updateWithOnConflict(var0, var1, var2, var3, var4);
|
||||||
|
return updateRes;
|
||||||
|
};
|
||||||
|
|
||||||
|
});
|
||||||
|
});
|
172
code/aesinfo.js
Normal file
172
code/aesinfo.js
Normal file
@ -0,0 +1,172 @@
|
|||||||
|
Java.perform(function() {
|
||||||
|
|
||||||
|
var use_single_byte = false;
|
||||||
|
var complete_bytes = new Array();
|
||||||
|
var index = 0;
|
||||||
|
|
||||||
|
|
||||||
|
var secretKeySpecDef = Java.use('javax.crypto.spec.SecretKeySpec');
|
||||||
|
|
||||||
|
var ivParameterSpecDef = Java.use('javax.crypto.spec.IvParameterSpec');
|
||||||
|
|
||||||
|
var cipherDef = Java.use('javax.crypto.Cipher');
|
||||||
|
|
||||||
|
var cipherDoFinal_1 = cipherDef.doFinal.overload();
|
||||||
|
var cipherDoFinal_2 = cipherDef.doFinal.overload('[B');
|
||||||
|
var cipherDoFinal_3 = cipherDef.doFinal.overload('[B', 'int');
|
||||||
|
var cipherDoFinal_4 = cipherDef.doFinal.overload('[B', 'int', 'int');
|
||||||
|
var cipherDoFinal_5 = cipherDef.doFinal.overload('[B', 'int', 'int', '[B');
|
||||||
|
var cipherDoFinal_6 = cipherDef.doFinal.overload('[B', 'int', 'int', '[B', 'int');
|
||||||
|
|
||||||
|
var cipherUpdate_1 = cipherDef.update.overload('[B');
|
||||||
|
var cipherUpdate_2 = cipherDef.update.overload('[B', 'int', 'int');
|
||||||
|
var cipherUpdate_3 = cipherDef.update.overload('[B', 'int', 'int', '[B');
|
||||||
|
var cipherUpdate_4 = cipherDef.update.overload('[B', 'int', 'int', '[B', 'int');
|
||||||
|
|
||||||
|
var secretKeySpecDef_init_1 = secretKeySpecDef.$init.overload('[B', 'java.lang.String');
|
||||||
|
|
||||||
|
var secretKeySpecDef_init_2 = secretKeySpecDef.$init.overload('[B', 'int', 'int', 'java.lang.String');
|
||||||
|
|
||||||
|
var ivParameterSpecDef_init_1 = ivParameterSpecDef.$init.overload('[B');
|
||||||
|
|
||||||
|
var ivParameterSpecDef_init_2 = ivParameterSpecDef.$init.overload('[B', 'int', 'int');
|
||||||
|
|
||||||
|
secretKeySpecDef_init_1.implementation = function(arr, alg) {
|
||||||
|
var key = b2s(arr);
|
||||||
|
send("Creating " + alg + " secret key, plaintext:\\n" + hexdump(key));
|
||||||
|
return secretKeySpecDef_init_1.call(this, arr, alg);
|
||||||
|
}
|
||||||
|
|
||||||
|
secretKeySpecDef_init_2.implementation = function(arr, off, len, alg) {
|
||||||
|
var key = b2s(arr);
|
||||||
|
send("Creating " + alg + " secret key, plaintext:\\n" + hexdump(key));
|
||||||
|
return secretKeySpecDef_init_2.call(this, arr, off, len, alg);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*ivParameterSpecDef_init_1.implementation = function(arr)
|
||||||
|
{
|
||||||
|
var iv = b2s(arr);
|
||||||
|
send("Creating IV:\\n" + hexdump(iv));
|
||||||
|
return ivParameterSpecDef_init_1.call(this, arr);
|
||||||
|
}
|
||||||
|
|
||||||
|
ivParameterSpecDef_init_2.implementation = function(arr, off, len)
|
||||||
|
{
|
||||||
|
var iv = b2s(arr);
|
||||||
|
send("Creating IV, plaintext:\\n" + hexdump(iv));
|
||||||
|
return ivParameterSpecDef_init_2.call(this, arr, off, len);
|
||||||
|
}*/
|
||||||
|
|
||||||
|
cipherDoFinal_1.implementation = function() {
|
||||||
|
var ret = cipherDoFinal_1.call(this);
|
||||||
|
info(this.getIV(), this.getAlgorithm(), complete_bytes, ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
cipherDoFinal_2.implementation = function(arr) {
|
||||||
|
addtoarray(arr);
|
||||||
|
var ret = cipherDoFinal_2.call(this, arr);
|
||||||
|
info(this.getIV(), this.getAlgorithm(), complete_bytes, ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
cipherDoFinal_3.implementation = function(arr, a) {
|
||||||
|
addtoarray(arr);
|
||||||
|
var ret = cipherDoFinal_3.call(this, arr, a);
|
||||||
|
info(this.getIV(), this.getAlgorithm(), complete_bytes, ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
cipherDoFinal_4.implementation = function(arr, a, b) {
|
||||||
|
addtoarray(arr);
|
||||||
|
var ret = cipherDoFinal_4.call(this, arr, a, b);
|
||||||
|
info(this.getIV(), this.getAlgorithm(), complete_bytes, ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
cipherDoFinal_5.implementation = function(arr, a, b, c) {
|
||||||
|
addtoarray(arr);
|
||||||
|
var ret = cipherDoFinal_5.call(this, arr, a, b, c);
|
||||||
|
info(this.getIV(), this.getAlgorithm(), complete_bytes, ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
cipherDoFinal_6.implementation = function(arr, a, b, c, d) {
|
||||||
|
addtoarray(arr);
|
||||||
|
var ret = cipherDoFinal_6.call(this, arr, a, b, c, d);
|
||||||
|
info(this.getIV(), this.getAlgorithm(), complete_bytes, c);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
cipherUpdate_1.implementation = function(arr) {
|
||||||
|
addtoarray(arr);
|
||||||
|
return cipherUpdate_1.call(this, arr);
|
||||||
|
}
|
||||||
|
|
||||||
|
cipherUpdate_2.implementation = function(arr, a, b) {
|
||||||
|
addtoarray(arr);
|
||||||
|
return cipherUpdate_2.call(this, arr, a, b);
|
||||||
|
}
|
||||||
|
|
||||||
|
cipherUpdate_3.implementation = function(arr, a, b, c) {
|
||||||
|
addtoarray(arr);
|
||||||
|
return cipherUpdate_3.call(this, arr, a, b, c);
|
||||||
|
}
|
||||||
|
|
||||||
|
cipherUpdate_4.implementation = function(arr, a, b, c, d) {
|
||||||
|
addtoarray(arr);
|
||||||
|
return cipherUpdate_4.call(this, arr, a, b, c, d);
|
||||||
|
}
|
||||||
|
|
||||||
|
function info(iv, alg, plain, encoded) {
|
||||||
|
send("Performing encryption/decryption");
|
||||||
|
if (iv) {
|
||||||
|
send("Initialization Vector: \\n" + hexdump(b2s(iv)));
|
||||||
|
} else {
|
||||||
|
send("Initialization Vector: " + iv);
|
||||||
|
}
|
||||||
|
send("Algorithm: " + alg);
|
||||||
|
send("In: \\n" + hexdump(b2s(plain)));
|
||||||
|
send("Out: \\n" + hexdump(b2s(encoded)));
|
||||||
|
complete_bytes = [];
|
||||||
|
index = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
function hexdump(buffer, blockSize) {
|
||||||
|
blockSize = blockSize || 16;
|
||||||
|
var lines = [];
|
||||||
|
var hex = "0123456789ABCDEF";
|
||||||
|
for (var b = 0; b < buffer.length; b += blockSize) {
|
||||||
|
var block = buffer.slice(b, Math.min(b + blockSize, buffer.length));
|
||||||
|
var addr = ("0000" + b.toString(16)).slice(-4);
|
||||||
|
var codes = block.split('').map(function(ch) {
|
||||||
|
var code = ch.charCodeAt(0);
|
||||||
|
return " " + hex[(0xF0 & code) >> 4] + hex[0x0F & code];
|
||||||
|
}).join("");
|
||||||
|
codes += " ".repeat(blockSize - block.length);
|
||||||
|
var chars = block.replace(/[\\x00-\\x1F\\x20]/g, '.');
|
||||||
|
chars += " ".repeat(blockSize - block.length);
|
||||||
|
lines.push(addr + " " + codes + " " + chars);
|
||||||
|
}
|
||||||
|
return lines.join("\\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
function b2s(array) {
|
||||||
|
var result = "";
|
||||||
|
for (var i = 0; i < array.length; i++) {
|
||||||
|
result += String.fromCharCode(modulus(array[i], 256));
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
function modulus(x, n) {
|
||||||
|
return ((x % n) + n) % n;
|
||||||
|
}
|
||||||
|
|
||||||
|
function addtoarray(arr) {
|
||||||
|
for (var i = 0; i < arr.length; i++) {
|
||||||
|
complete_bytes[index] = arr[i];
|
||||||
|
index = index + 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
13
code/cordova---enable-webview-debugging.js
vendored
Normal file
13
code/cordova---enable-webview-debugging.js
vendored
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
// Usage : frida -U -f bundle_id -l enable_debug.js --no-pause
|
||||||
|
// Blog link to be added
|
||||||
|
// Written by @67616d654661636 and @sunnyrockzzs
|
||||||
|
|
||||||
|
Java.perform(function() {
|
||||||
|
var Webview = Java.use("android.webkit.WebView")
|
||||||
|
Webview.loadUrl.overload("java.lang.String").implementation = function(url) {
|
||||||
|
console.log("\n[+]Loading URL from", url);
|
||||||
|
console.log("[+]Setting the value of setWebContentsDebuggingEnabled() to TRUE");
|
||||||
|
this.setWebContentsDebuggingEnabled(true);
|
||||||
|
this.loadUrl.overload("java.lang.String").call(this, url);
|
||||||
|
}
|
||||||
|
});
|
730
code/frida-multiple-unpinning.js
Normal file
730
code/frida-multiple-unpinning.js
Normal file
@ -0,0 +1,730 @@
|
|||||||
|
/* Android ssl certificate pinning bypass script for various methods
|
||||||
|
by Maurizio Siddu
|
||||||
|
|
||||||
|
Run with:
|
||||||
|
frida -U -f [APP_ID] -l frida_multiple_unpinning.js --no-pause
|
||||||
|
*/
|
||||||
|
|
||||||
|
setTimeout(function() {
|
||||||
|
Java.perform(function() {
|
||||||
|
console.log('');
|
||||||
|
console.log('======');
|
||||||
|
console.log('[#] Android Bypass for various Certificate Pinning methods [#]');
|
||||||
|
console.log('======');
|
||||||
|
|
||||||
|
|
||||||
|
var X509TrustManager = Java.use('javax.net.ssl.X509TrustManager');
|
||||||
|
var SSLContext = Java.use('javax.net.ssl.SSLContext');
|
||||||
|
|
||||||
|
// TrustManager (Android < 7) //
|
||||||
|
////////////////////////////////
|
||||||
|
var TrustManager = Java.registerClass({
|
||||||
|
// Implement a custom TrustManager
|
||||||
|
name: 'dev.asd.test.TrustManager',
|
||||||
|
implements: [X509TrustManager],
|
||||||
|
methods: {
|
||||||
|
checkClientTrusted: function(chain, authType) {},
|
||||||
|
checkServerTrusted: function(chain, authType) {},
|
||||||
|
getAcceptedIssuers: function() {return []; }
|
||||||
|
}
|
||||||
|
});
|
||||||
|
// Prepare the TrustManager array to pass to SSLContext.init()
|
||||||
|
var TrustManagers = [TrustManager.$new()];
|
||||||
|
// Get a handle on the init() on the SSLContext class
|
||||||
|
var SSLContext_init = SSLContext.init.overload(
|
||||||
|
'[Ljavax.net.ssl.KeyManager;', '[Ljavax.net.ssl.TrustManager;', 'java.security.SecureRandom');
|
||||||
|
try {
|
||||||
|
// Override the init method, specifying the custom TrustManager
|
||||||
|
SSLContext_init.implementation = function(keyManager, trustManager, secureRandom) {
|
||||||
|
console.log('[+] Bypassing Trustmanager (Android < 7) pinner');
|
||||||
|
SSLContext_init.call(this, keyManager, TrustManagers, secureRandom);
|
||||||
|
};
|
||||||
|
} catch (err) {
|
||||||
|
console.log('[-] TrustManager (Android < 7) pinner not found');
|
||||||
|
//console.log(err);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// OkHTTPv3 (quadruple bypass) //
|
||||||
|
/////////////////////////////////
|
||||||
|
try {
|
||||||
|
// Bypass OkHTTPv3 {1}
|
||||||
|
var okhttp3_Activity_1 = Java.use('okhttp3.CertificatePinner');
|
||||||
|
okhttp3_Activity_1.check.overload('java.lang.String', 'java.util.List').implementation = function(a, b) {
|
||||||
|
console.log('[+] Bypassing OkHTTPv3 {1}: ' + a);
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
} catch (err) {
|
||||||
|
console.log('[-] OkHTTPv3 {1} pinner not found');
|
||||||
|
//console.log(err);
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
// Bypass OkHTTPv3 {2}
|
||||||
|
// This method of CertificatePinner.check is deprecated but could be found in some old Android apps
|
||||||
|
var okhttp3_Activity_2 = Java.use('okhttp3.CertificatePinner');
|
||||||
|
okhttp3_Activity_2.check.overload('java.lang.String', 'java.security.cert.Certificate').implementation = function(a, b) {
|
||||||
|
console.log('[+] Bypassing OkHTTPv3 {2}: ' + a);
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
} catch (err) {
|
||||||
|
console.log('[-] OkHTTPv3 {2} pinner not found');
|
||||||
|
//console.log(err);
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
// Bypass OkHTTPv3 {3}
|
||||||
|
var okhttp3_Activity_3 = Java.use('okhttp3.CertificatePinner');
|
||||||
|
okhttp3_Activity_3.check.overload('java.lang.String', '[Ljava.security.cert.Certificate;').implementation = function(a, b) {
|
||||||
|
console.log('[+] Bypassing OkHTTPv3 {3}: ' + a);
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
} catch(err) {
|
||||||
|
console.log('[-] OkHTTPv3 {3} pinner not found');
|
||||||
|
//console.log(err);
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
// Bypass OkHTTPv3 {4}
|
||||||
|
var okhttp3_Activity_4 = Java.use('okhttp3.CertificatePinner');
|
||||||
|
//okhttp3_Activity_4['check$okhttp'].implementation = function(a, b) {
|
||||||
|
okhttp3_Activity_4.check$okhttp.overload('java.lang.String', 'kotlin.jvm.functions.Function0').implementation = function(a, b) {
|
||||||
|
console.log('[+] Bypassing OkHTTPv3 {4}: ' + a);
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
} catch(err) {
|
||||||
|
console.log('[-] OkHTTPv3 {4} pinner not found');
|
||||||
|
//console.log(err);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// Trustkit (triple bypass) //
|
||||||
|
//////////////////////////////
|
||||||
|
try {
|
||||||
|
// Bypass Trustkit {1}
|
||||||
|
var trustkit_Activity_1 = Java.use('com.datatheorem.android.trustkit.pinning.OkHostnameVerifier');
|
||||||
|
trustkit_Activity_1.verify.overload('java.lang.String', 'javax.net.ssl.SSLSession').implementation = function(a, b) {
|
||||||
|
console.log('[+] Bypassing Trustkit {1}: ' + a);
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
} catch (err) {
|
||||||
|
console.log('[-] Trustkit {1} pinner not found');
|
||||||
|
//console.log(err);
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
// Bypass Trustkit {2}
|
||||||
|
var trustkit_Activity_2 = Java.use('com.datatheorem.android.trustkit.pinning.OkHostnameVerifier');
|
||||||
|
trustkit_Activity_2.verify.overload('java.lang.String', 'java.security.cert.X509Certificate').implementation = function(a, b) {
|
||||||
|
console.log('[+] Bypassing Trustkit {2}: ' + a);
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
} catch (err) {
|
||||||
|
console.log('[-] Trustkit {2} pinner not found');
|
||||||
|
//console.log(err);
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
// Bypass Trustkit {3}
|
||||||
|
var trustkit_PinningTrustManager = Java.use('com.datatheorem.android.trustkit.pinning.PinningTrustManager');
|
||||||
|
trustkit_PinningTrustManager.checkServerTrusted.overload('[Ljava.security.cert.X509Certificate;', 'java.lang.String').implementation = function(chain, authType) {
|
||||||
|
console.log('[+] Bypassing Trustkit {3}');
|
||||||
|
//return;
|
||||||
|
};
|
||||||
|
} catch (err) {
|
||||||
|
console.log('[-] Trustkit {3} pinner not found');
|
||||||
|
//console.log(err);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// TrustManagerImpl (Android > 7) //
|
||||||
|
////////////////////////////////////
|
||||||
|
try {
|
||||||
|
// Bypass TrustManagerImpl (Android > 7) {1}
|
||||||
|
var array_list = Java.use("java.util.ArrayList");
|
||||||
|
var TrustManagerImpl_Activity_1 = Java.use('com.android.org.conscrypt.TrustManagerImpl');
|
||||||
|
TrustManagerImpl_Activity_1.checkTrustedRecursive.implementation = function(certs, ocspData, tlsSctData, host, clientAuth, untrustedChain, trustAnchorChain, used) {
|
||||||
|
console.log('[+] Bypassing TrustManagerImpl (Android > 7) checkTrustedRecursive check: '+ host);
|
||||||
|
return array_list.$new();
|
||||||
|
};
|
||||||
|
} catch (err) {
|
||||||
|
console.log('[-] TrustManagerImpl (Android > 7) checkTrustedRecursive check not found');
|
||||||
|
//console.log(err);
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
// Bypass TrustManagerImpl (Android > 7) {2} (probably no more necessary)
|
||||||
|
var TrustManagerImpl_Activity_2 = Java.use('com.android.org.conscrypt.TrustManagerImpl');
|
||||||
|
TrustManagerImpl_Activity_2.verifyChain.implementation = function(untrustedChain, trustAnchorChain, host, clientAuth, ocspData, tlsSctData) {
|
||||||
|
console.log('[+] Bypassing TrustManagerImpl (Android > 7) verifyChain check: ' + host);
|
||||||
|
return untrustedChain;
|
||||||
|
};
|
||||||
|
} catch (err) {
|
||||||
|
console.log('[-] TrustManagerImpl (Android > 7) verifyChain check not found');
|
||||||
|
//console.log(err);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// Appcelerator Titanium PinningTrustManager //
|
||||||
|
///////////////////////////////////////////////
|
||||||
|
try {
|
||||||
|
var appcelerator_PinningTrustManager = Java.use('appcelerator.https.PinningTrustManager');
|
||||||
|
appcelerator_PinningTrustManager.checkServerTrusted.implementation = function(chain, authType) {
|
||||||
|
console.log('[+] Bypassing Appcelerator PinningTrustManager');
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
} catch (err) {
|
||||||
|
console.log('[-] Appcelerator PinningTrustManager pinner not found');
|
||||||
|
//console.log(err);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// Fabric PinningTrustManager //
|
||||||
|
////////////////////////////////
|
||||||
|
try {
|
||||||
|
var fabric_PinningTrustManager = Java.use('io.fabric.sdk.android.services.network.PinningTrustManager');
|
||||||
|
fabric_PinningTrustManager.checkServerTrusted.implementation = function(chain, authType) {
|
||||||
|
console.log('[+] Bypassing Fabric PinningTrustManager');
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
} catch (err) {
|
||||||
|
console.log('[-] Fabric PinningTrustManager pinner not found');
|
||||||
|
//console.log(err);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// OpenSSLSocketImpl Conscrypt (double bypass) //
|
||||||
|
/////////////////////////////////////////////////
|
||||||
|
try {
|
||||||
|
var OpenSSLSocketImpl = Java.use('com.android.org.conscrypt.OpenSSLSocketImpl');
|
||||||
|
OpenSSLSocketImpl.verifyCertificateChain.implementation = function(certRefs, JavaObject, authMethod) {
|
||||||
|
console.log('[+] Bypassing OpenSSLSocketImpl Conscrypt {1}');
|
||||||
|
};
|
||||||
|
} catch (err) {
|
||||||
|
console.log('[-] OpenSSLSocketImpl Conscrypt {1} pinner not found');
|
||||||
|
//console.log(err);
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
var OpenSSLSocketImpl = Java.use('com.android.org.conscrypt.OpenSSLSocketImpl');
|
||||||
|
OpenSSLSocketImpl.verifyCertificateChain.implementation = function(certChain, authMethod) {
|
||||||
|
console.log('[+] Bypassing OpenSSLSocketImpl Conscrypt {2}');
|
||||||
|
};
|
||||||
|
} catch (err) {
|
||||||
|
console.log('[-] OpenSSLSocketImpl Conscrypt {2} pinner not found');
|
||||||
|
//console.log(err);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// OpenSSLEngineSocketImpl Conscrypt //
|
||||||
|
///////////////////////////////////////
|
||||||
|
try {
|
||||||
|
var OpenSSLEngineSocketImpl_Activity = Java.use('com.android.org.conscrypt.OpenSSLEngineSocketImpl');
|
||||||
|
OpenSSLEngineSocketImpl_Activity.verifyCertificateChain.overload('[Ljava.lang.Long;', 'java.lang.String').implementation = function(a, b) {
|
||||||
|
console.log('[+] Bypassing OpenSSLEngineSocketImpl Conscrypt: ' + b);
|
||||||
|
};
|
||||||
|
} catch (err) {
|
||||||
|
console.log('[-] OpenSSLEngineSocketImpl Conscrypt pinner not found');
|
||||||
|
//console.log(err);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// OpenSSLSocketImpl Apache Harmony //
|
||||||
|
//////////////////////////////////////
|
||||||
|
try {
|
||||||
|
var OpenSSLSocketImpl_Harmony = Java.use('org.apache.harmony.xnet.provider.jsse.OpenSSLSocketImpl');
|
||||||
|
OpenSSLSocketImpl_Harmony.verifyCertificateChain.implementation = function(asn1DerEncodedCertificateChain, authMethod) {
|
||||||
|
console.log('[+] Bypassing OpenSSLSocketImpl Apache Harmony');
|
||||||
|
};
|
||||||
|
} catch (err) {
|
||||||
|
console.log('[-] OpenSSLSocketImpl Apache Harmony pinner not found');
|
||||||
|
//console.log(err);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// PhoneGap sslCertificateChecker //
|
||||||
|
////////////////////////////////////
|
||||||
|
try {
|
||||||
|
var phonegap_Activity = Java.use('nl.xservices.plugins.sslCertificateChecker');
|
||||||
|
phonegap_Activity.execute.overload('java.lang.String', 'org.json.JSONArray', 'org.apache.cordova.CallbackContext').implementation = function(a, b, c) {
|
||||||
|
console.log('[+] Bypassing PhoneGap sslCertificateChecker: ' + a);
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
} catch (err) {
|
||||||
|
console.log('[-] PhoneGap sslCertificateChecker pinner not found');
|
||||||
|
//console.log(err);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// IBM MobileFirst pinTrustedCertificatePublicKey (double bypass) //
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
try {
|
||||||
|
// Bypass IBM MobileFirst {1}
|
||||||
|
var WLClient_Activity_1 = Java.use('com.worklight.wlclient.api.WLClient');
|
||||||
|
WLClient_Activity_1.getInstance().pinTrustedCertificatePublicKey.overload('java.lang.String').implementation = function(cert) {
|
||||||
|
console.log('[+] Bypassing IBM MobileFirst pinTrustedCertificatePublicKey {1}: ' + cert);
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
} catch (err) {
|
||||||
|
console.log('[-] IBM MobileFirst pinTrustedCertificatePublicKey {1} pinner not found');
|
||||||
|
//console.log(err);
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
// Bypass IBM MobileFirst {2}
|
||||||
|
var WLClient_Activity_2 = Java.use('com.worklight.wlclient.api.WLClient');
|
||||||
|
WLClient_Activity_2.getInstance().pinTrustedCertificatePublicKey.overload('[Ljava.lang.String;').implementation = function(cert) {
|
||||||
|
console.log('[+] Bypassing IBM MobileFirst pinTrustedCertificatePublicKey {2}: ' + cert);
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
} catch (err) {
|
||||||
|
console.log('[-] IBM MobileFirst pinTrustedCertificatePublicKey {2} pinner not found');
|
||||||
|
//console.log(err);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// IBM WorkLight (ancestor of MobileFirst) HostNameVerifierWithCertificatePinning (quadruple bypass) //
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
try {
|
||||||
|
// Bypass IBM WorkLight {1}
|
||||||
|
var worklight_Activity_1 = Java.use('com.worklight.wlclient.certificatepinning.HostNameVerifierWithCertificatePinning');
|
||||||
|
worklight_Activity_1.verify.overload('java.lang.String', 'javax.net.ssl.SSLSocket').implementation = function(a, b) {
|
||||||
|
console.log('[+] Bypassing IBM WorkLight HostNameVerifierWithCertificatePinning {1}: ' + a);
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
} catch (err) {
|
||||||
|
console.log('[-] IBM WorkLight HostNameVerifierWithCertificatePinning {1} pinner not found');
|
||||||
|
//console.log(err);
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
// Bypass IBM WorkLight {2}
|
||||||
|
var worklight_Activity_2 = Java.use('com.worklight.wlclient.certificatepinning.HostNameVerifierWithCertificatePinning');
|
||||||
|
worklight_Activity_2.verify.overload('java.lang.String', 'java.security.cert.X509Certificate').implementation = function(a, b) {
|
||||||
|
console.log('[+] Bypassing IBM WorkLight HostNameVerifierWithCertificatePinning {2}: ' + a);
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
} catch (err) {
|
||||||
|
console.log('[-] IBM WorkLight HostNameVerifierWithCertificatePinning {2} pinner not found');
|
||||||
|
//console.log(err);
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
// Bypass IBM WorkLight {3}
|
||||||
|
var worklight_Activity_3 = Java.use('com.worklight.wlclient.certificatepinning.HostNameVerifierWithCertificatePinning');
|
||||||
|
worklight_Activity_3.verify.overload('java.lang.String', '[Ljava.lang.String;', '[Ljava.lang.String;').implementation = function(a, b) {
|
||||||
|
console.log('[+] Bypassing IBM WorkLight HostNameVerifierWithCertificatePinning {3}: ' + a);
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
} catch (err) {
|
||||||
|
console.log('[-] IBM WorkLight HostNameVerifierWithCertificatePinning {3} pinner not found');
|
||||||
|
//console.log(err);
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
// Bypass IBM WorkLight {4}
|
||||||
|
var worklight_Activity_4 = Java.use('com.worklight.wlclient.certificatepinning.HostNameVerifierWithCertificatePinning');
|
||||||
|
worklight_Activity_4.verify.overload('java.lang.String', 'javax.net.ssl.SSLSession').implementation = function(a, b) {
|
||||||
|
console.log('[+] Bypassing IBM WorkLight HostNameVerifierWithCertificatePinning {4}: ' + a);
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
} catch (err) {
|
||||||
|
console.log('[-] IBM WorkLight HostNameVerifierWithCertificatePinning {4} pinner not found');
|
||||||
|
//console.log(err);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// Conscrypt CertPinManager //
|
||||||
|
//////////////////////////////
|
||||||
|
try {
|
||||||
|
var conscrypt_CertPinManager_Activity = Java.use('com.android.org.conscrypt.CertPinManager');
|
||||||
|
conscrypt_CertPinManager_Activity.checkChainPinning.overload('java.lang.String', 'java.util.List').implementation = function(a, b) {
|
||||||
|
console.log('[+] Bypassing Conscrypt CertPinManager: ' + a);
|
||||||
|
//return;
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
} catch (err) {
|
||||||
|
console.log('[-] Conscrypt CertPinManager pinner not found');
|
||||||
|
//console.log(err);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// Conscrypt CertPinManager (Legacy) //
|
||||||
|
///////////////////////////////////////
|
||||||
|
try {
|
||||||
|
var legacy_conscrypt_CertPinManager_Activity = Java.use('com.android.org.conscrypt.CertPinManager');
|
||||||
|
legacy_conscrypt_CertPinManager_Activity.isChainValid.overload('java.lang.String', 'java.util.List').implementation = function(a, b) {
|
||||||
|
console.log('[+] Bypassing Conscrypt CertPinManager (Legacy): ' + a);
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
} catch (err) {
|
||||||
|
console.log('[-] Conscrypt CertPinManager (Legacy) pinner not found');
|
||||||
|
//console.log(err);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// CWAC-Netsecurity (unofficial back-port pinner for Android<4.2) CertPinManager //
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////
|
||||||
|
try {
|
||||||
|
var cwac_CertPinManager_Activity = Java.use('com.commonsware.cwac.netsecurity.conscrypt.CertPinManager');
|
||||||
|
cwac_CertPinManager_Activity.isChainValid.overload('java.lang.String', 'java.util.List').implementation = function(a, b) {
|
||||||
|
console.log('[+] Bypassing CWAC-Netsecurity CertPinManager: ' + a);
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
} catch (err) {
|
||||||
|
console.log('[-] CWAC-Netsecurity CertPinManager pinner not found');
|
||||||
|
//console.log(err);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// Worklight Androidgap WLCertificatePinningPlugin //
|
||||||
|
/////////////////////////////////////////////////////
|
||||||
|
try {
|
||||||
|
var androidgap_WLCertificatePinningPlugin_Activity = Java.use('com.worklight.androidgap.plugin.WLCertificatePinningPlugin');
|
||||||
|
androidgap_WLCertificatePinningPlugin_Activity.execute.overload('java.lang.String', 'org.json.JSONArray', 'org.apache.cordova.CallbackContext').implementation = function(a, b, c) {
|
||||||
|
console.log('[+] Bypassing Worklight Androidgap WLCertificatePinningPlugin: ' + a);
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
} catch (err) {
|
||||||
|
console.log('[-] Worklight Androidgap WLCertificatePinningPlugin pinner not found');
|
||||||
|
//console.log(err);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// Netty FingerprintTrustManagerFactory //
|
||||||
|
//////////////////////////////////////////
|
||||||
|
try {
|
||||||
|
var netty_FingerprintTrustManagerFactory = Java.use('io.netty.handler.ssl.util.FingerprintTrustManagerFactory');
|
||||||
|
//NOTE: sometimes this below implementation could be useful
|
||||||
|
//var netty_FingerprintTrustManagerFactory = Java.use('org.jboss.netty.handler.ssl.util.FingerprintTrustManagerFactory');
|
||||||
|
netty_FingerprintTrustManagerFactory.checkTrusted.implementation = function(type, chain) {
|
||||||
|
console.log('[+] Bypassing Netty FingerprintTrustManagerFactory');
|
||||||
|
};
|
||||||
|
} catch (err) {
|
||||||
|
console.log('[-] Netty FingerprintTrustManagerFactory pinner not found');
|
||||||
|
//console.log(err);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// Squareup CertificatePinner [OkHTTP<v3] (double bypass) //
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
try {
|
||||||
|
// Bypass Squareup CertificatePinner {1}
|
||||||
|
var Squareup_CertificatePinner_Activity_1 = Java.use('com.squareup.okhttp.CertificatePinner');
|
||||||
|
Squareup_CertificatePinner_Activity_1.check.overload('java.lang.String', 'java.security.cert.Certificate').implementation = function(a, b) {
|
||||||
|
console.log('[+] Bypassing Squareup CertificatePinner {1}: ' + a);
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
} catch (err) {
|
||||||
|
console.log('[-] Squareup CertificatePinner {1} pinner not found');
|
||||||
|
//console.log(err);
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
// Bypass Squareup CertificatePinner {2}
|
||||||
|
var Squareup_CertificatePinner_Activity_2 = Java.use('com.squareup.okhttp.CertificatePinner');
|
||||||
|
Squareup_CertificatePinner_Activity_2.check.overload('java.lang.String', 'java.util.List').implementation = function(a, b) {
|
||||||
|
console.log('[+] Bypassing Squareup CertificatePinner {2}: ' + a);
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
} catch (err) {
|
||||||
|
console.log('[-] Squareup CertificatePinner {2} pinner not found');
|
||||||
|
//console.log(err);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// Squareup OkHostnameVerifier [OkHTTP v3] (double bypass) //
|
||||||
|
/////////////////////////////////////////////////////////////
|
||||||
|
try {
|
||||||
|
// Bypass Squareup OkHostnameVerifier {1}
|
||||||
|
var Squareup_OkHostnameVerifier_Activity_1 = Java.use('com.squareup.okhttp.internal.tls.OkHostnameVerifier');
|
||||||
|
Squareup_OkHostnameVerifier_Activity_1.verify.overload('java.lang.String', 'java.security.cert.X509Certificate').implementation = function(a, b) {
|
||||||
|
console.log('[+] Bypassing Squareup OkHostnameVerifier {1}: ' + a);
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
} catch (err) {
|
||||||
|
console.log('[-] Squareup OkHostnameVerifier check not found');
|
||||||
|
//console.log(err);
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
// Bypass Squareup OkHostnameVerifier {2}
|
||||||
|
var Squareup_OkHostnameVerifier_Activity_2 = Java.use('com.squareup.okhttp.internal.tls.OkHostnameVerifier');
|
||||||
|
Squareup_OkHostnameVerifier_Activity_2.verify.overload('java.lang.String', 'javax.net.ssl.SSLSession').implementation = function(a, b) {
|
||||||
|
console.log('[+] Bypassing Squareup OkHostnameVerifier {2}: ' + a);
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
} catch (err) {
|
||||||
|
console.log('[-] Squareup OkHostnameVerifier check not found');
|
||||||
|
//console.log(err);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// Android WebViewClient (quadruple bypass) //
|
||||||
|
//////////////////////////////////////////////
|
||||||
|
try {
|
||||||
|
// Bypass WebViewClient {1} (deprecated from Android 6)
|
||||||
|
var AndroidWebViewClient_Activity_1 = Java.use('android.webkit.WebViewClient');
|
||||||
|
AndroidWebViewClient_Activity_1.onReceivedSslError.overload('android.webkit.WebView', 'android.webkit.SslErrorHandler', 'android.net.http.SslError').implementation = function(obj1, obj2, obj3) {
|
||||||
|
console.log('[+] Bypassing Android WebViewClient check {1}');
|
||||||
|
};
|
||||||
|
} catch (err) {
|
||||||
|
console.log('[-] Android WebViewClient {1} check not found');
|
||||||
|
//console.log(err)
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
// Bypass WebViewClient {2}
|
||||||
|
var AndroidWebViewClient_Activity_2 = Java.use('android.webkit.WebViewClient');
|
||||||
|
AndroidWebViewClient_Activity_2.onReceivedSslError.overload('android.webkit.WebView', 'android.webkit.WebResourceRequest', 'android.webkit.WebResourceError').implementation = function(obj1, obj2, obj3) {
|
||||||
|
console.log('[+] Bypassing Android WebViewClient check {2}');
|
||||||
|
};
|
||||||
|
} catch (err) {
|
||||||
|
console.log('[-] Android WebViewClient {2} check not found');
|
||||||
|
//console.log(err)
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
// Bypass WebViewClient {3}
|
||||||
|
var AndroidWebViewClient_Activity_3 = Java.use('android.webkit.WebViewClient');
|
||||||
|
AndroidWebViewClient_Activity_3.onReceivedError.overload('android.webkit.WebView', 'int', 'java.lang.String', 'java.lang.String').implementation = function(obj1, obj2, obj3, obj4) {
|
||||||
|
console.log('[+] Bypassing Android WebViewClient check {3}');
|
||||||
|
};
|
||||||
|
} catch (err) {
|
||||||
|
console.log('[-] Android WebViewClient {3} check not found');
|
||||||
|
//console.log(err)
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
// Bypass WebViewClient {4}
|
||||||
|
var AndroidWebViewClient_Activity_4 = Java.use('android.webkit.WebViewClient');
|
||||||
|
AndroidWebViewClient_Activity_4.onReceivedError.overload('android.webkit.WebView', 'android.webkit.WebResourceRequest', 'android.webkit.WebResourceError').implementation = function(obj1, obj2, obj3) {
|
||||||
|
console.log('[+] Bypassing Android WebViewClient check {4}');
|
||||||
|
};
|
||||||
|
} catch (err) {
|
||||||
|
console.log('[-] Android WebViewClient {4} check not found');
|
||||||
|
//console.log(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// Apache Cordova WebViewClient //
|
||||||
|
//////////////////////////////////
|
||||||
|
try {
|
||||||
|
var CordovaWebViewClient_Activity = Java.use('org.apache.cordova.CordovaWebViewClient');
|
||||||
|
CordovaWebViewClient_Activity.onReceivedSslError.overload('android.webkit.WebView', 'android.webkit.SslErrorHandler', 'android.net.http.SslError').implementation = function(obj1, obj2, obj3) {
|
||||||
|
console.log('[+] Bypassing Apache Cordova WebViewClient check');
|
||||||
|
obj3.proceed();
|
||||||
|
};
|
||||||
|
} catch (err) {
|
||||||
|
console.log('[-] Apache Cordova WebViewClient check not found');
|
||||||
|
//console.log(err);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// Boye AbstractVerifier //
|
||||||
|
///////////////////////////
|
||||||
|
try {
|
||||||
|
var boye_AbstractVerifier = Java.use('ch.boye.httpclientandroidlib.conn.ssl.AbstractVerifier');
|
||||||
|
boye_AbstractVerifier.verify.implementation = function(host, ssl) {
|
||||||
|
console.log('[+] Bypassing Boye AbstractVerifier check: ' + host);
|
||||||
|
};
|
||||||
|
} catch (err) {
|
||||||
|
console.log('[-] Boye AbstractVerifier check not found');
|
||||||
|
//console.log(err);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// Apache AbstractVerifier //
|
||||||
|
/////////////////////////////
|
||||||
|
try {
|
||||||
|
var apache_AbstractVerifier = Java.use('org.apache.http.conn.ssl.AbstractVerifier');
|
||||||
|
apache_AbstractVerifier.verify.implementation = function(a, b, c, d) {
|
||||||
|
console.log('[+] Bypassing Apache AbstractVerifier check: ' + a);
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
} catch (err) {
|
||||||
|
console.log('[-] Apache AbstractVerifier check not found');
|
||||||
|
//console.log(err);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// Chromium Cronet //
|
||||||
|
/////////////////////
|
||||||
|
try {
|
||||||
|
var CronetEngineBuilderImpl_Activity = Java.use("org.chromium.net.impl.CronetEngineBuilderImpl");
|
||||||
|
// Setting argument to TRUE (default is TRUE) to disable Public Key pinning for local trust anchors
|
||||||
|
CronetEngine_Activity.enablePublicKeyPinningBypassForLocalTrustAnchors.overload('boolean').implementation = function(a) {
|
||||||
|
console.log("[+] Disabling Public Key pinning for local trust anchors in Chromium Cronet");
|
||||||
|
var cronet_obj_1 = CronetEngine_Activity.enablePublicKeyPinningBypassForLocalTrustAnchors.call(this, true);
|
||||||
|
return cronet_obj_1;
|
||||||
|
};
|
||||||
|
// Bypassing Chromium Cronet pinner
|
||||||
|
CronetEngine_Activity.addPublicKeyPins.overload('java.lang.String', 'java.util.Set', 'boolean', 'java.util.Date').implementation = function(hostName, pinsSha256, includeSubdomains, expirationDate) {
|
||||||
|
console.log("[+] Bypassing Chromium Cronet pinner: " + hostName);
|
||||||
|
var cronet_obj_2 = CronetEngine_Activity.addPublicKeyPins.call(this, hostName, pinsSha256, includeSubdomains, expirationDate);
|
||||||
|
return cronet_obj_2;
|
||||||
|
};
|
||||||
|
} catch (err) {
|
||||||
|
console.log('[-] Chromium Cronet pinner not found')
|
||||||
|
//console.log(err);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// Flutter Pinning packages http_certificate_pinning and ssl_pinning_plugin (double bypass) //
|
||||||
|
//////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
try {
|
||||||
|
// Bypass HttpCertificatePinning.check {1}
|
||||||
|
var HttpCertificatePinning_Activity = Java.use('diefferson.http_certificate_pinning.HttpCertificatePinning');
|
||||||
|
HttpCertificatePinning_Activity.checkConnexion.overload("java.lang.String", "java.util.List", "java.util.Map", "int", "java.lang.String").implementation = function (a, b, c ,d, e) {
|
||||||
|
console.log('[+] Bypassing Flutter HttpCertificatePinning : ' + a);
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
} catch (err) {
|
||||||
|
console.log('[-] Flutter HttpCertificatePinning pinner not found');
|
||||||
|
//console.log(err);
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
// Bypass SslPinningPlugin.check {2}
|
||||||
|
var SslPinningPlugin_Activity = Java.use('com.macif.plugin.sslpinningplugin.SslPinningPlugin');
|
||||||
|
SslPinningPlugin_Activity.checkConnexion.overload("java.lang.String", "java.util.List", "java.util.Map", "int", "java.lang.String").implementation = function (a, b, c ,d, e) {
|
||||||
|
console.log('[+] Bypassing Flutter SslPinningPlugin: ' + a);
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
} catch (err) {
|
||||||
|
console.log('[-] Flutter SslPinningPlugin pinner not found');
|
||||||
|
//console.log(err);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// Dynamic SSLPeerUnverifiedException Patcher //
|
||||||
|
// An useful technique to bypass SSLPeerUnverifiedException failures raising //
|
||||||
|
// when the Android app uses some uncommon SSL Pinning methods or an heavily //
|
||||||
|
// code obfuscation. Inspired by an idea of: https://github.com/httptoolkit //
|
||||||
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
function rudimentaryFix(typeName) {
|
||||||
|
// This is a improvable rudimentary fix, if not works you can patch it manually
|
||||||
|
if (typeName === undefined){
|
||||||
|
return;
|
||||||
|
} else if (typeName === 'boolean') {
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
var UnverifiedCertError = Java.use('javax.net.ssl.SSLPeerUnverifiedException');
|
||||||
|
UnverifiedCertError.$init.implementation = function (str) {
|
||||||
|
console.log('\x1b[36m[!] Unexpected SSLPeerUnverifiedException occurred, trying to patch it dynamically...\x1b[0m');
|
||||||
|
try {
|
||||||
|
var stackTrace = Java.use('java.lang.Thread').currentThread().getStackTrace();
|
||||||
|
var exceptionStackIndex = stackTrace.findIndex(stack =>
|
||||||
|
stack.getClassName() === "javax.net.ssl.SSLPeerUnverifiedException"
|
||||||
|
);
|
||||||
|
// Retrieve the method raising the SSLPeerUnverifiedException
|
||||||
|
var callingFunctionStack = stackTrace[exceptionStackIndex + 1];
|
||||||
|
var className = callingFunctionStack.getClassName();
|
||||||
|
var methodName = callingFunctionStack.getMethodName();
|
||||||
|
var callingClass = Java.use(className);
|
||||||
|
var callingMethod = callingClass[methodName];
|
||||||
|
console.log('\x1b[36m[!] Attempting to bypass uncommon SSL Pinning method on: '+className+'.'+methodName+'\x1b[0m');
|
||||||
|
// Skip it when already patched by Frida
|
||||||
|
if (callingMethod.implementation) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// Trying to patch the uncommon SSL Pinning method via implementation
|
||||||
|
var returnTypeName = callingMethod.returnType.type;
|
||||||
|
callingMethod.implementation = function() {
|
||||||
|
rudimentaryFix(returnTypeName);
|
||||||
|
};
|
||||||
|
} catch (e) {
|
||||||
|
// Dynamic patching via implementation does not works, then trying via function overloading
|
||||||
|
//console.log('[!] The uncommon SSL Pinning method has more than one overload);
|
||||||
|
if (String(e).includes(".overload")) {
|
||||||
|
var splittedList = String(e).split(".overload");
|
||||||
|
for (let i=2; i<splittedList.length; i++) {
|
||||||
|
var extractedOverload = splittedList[i].trim().split("(")[1].slice(0,-1).replaceAll("'","");
|
||||||
|
// Check if extractedOverload has multiple arguments
|
||||||
|
if (extractedOverload.includes(",")) {
|
||||||
|
// Go here if overloaded method has multiple arguments (NOTE: max 6 args are covered here)
|
||||||
|
var argList = extractedOverload.split(", ");
|
||||||
|
console.log('\x1b[36m[!] Attempting overload of '+className+'.'+methodName+' with arguments: '+extractedOverload+'\x1b[0m');
|
||||||
|
if (argList.length == 2) {
|
||||||
|
callingMethod.overload(argList[0], argList[1]).implementation = function(a,b) {
|
||||||
|
rudimentaryFix(returnTypeName);
|
||||||
|
}
|
||||||
|
} else if (argNum == 3) {
|
||||||
|
callingMethod.overload(argList[0], argList[1], argList[2]).implementation = function(a,b,c) {
|
||||||
|
rudimentaryFix(returnTypeName);
|
||||||
|
}
|
||||||
|
} else if (argNum == 4) {
|
||||||
|
callingMethod.overload(argList[0], argList[1], argList[2], argList[3]).implementation = function(a,b,c,d) {
|
||||||
|
rudimentaryFix(returnTypeName);
|
||||||
|
}
|
||||||
|
} else if (argNum == 5) {
|
||||||
|
callingMethod.overload(argList[0], argList[1], argList[2], argList[3], argList[4]).implementation = function(a,b,c,d,e) {
|
||||||
|
rudimentaryFix(returnTypeName);
|
||||||
|
}
|
||||||
|
} else if (argNum == 6) {
|
||||||
|
callingMethod.overload(argList[0], argList[1], argList[2], argList[3], argList[4], argList[5]).implementation = function(a,b,c,d,e,f) {
|
||||||
|
rudimentaryFix(returnTypeName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Go here if overloaded method has a single argument
|
||||||
|
} else {
|
||||||
|
callingMethod.overload(extractedOverload).implementation = function(a) {
|
||||||
|
rudimentaryFix(returnTypeName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
console.log('\x1b[36m[-] Failed to dynamically patch SSLPeerUnverifiedException '+e+'\x1b[0m');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//console.log('\x1b[36m[+] SSLPeerUnverifiedException hooked\x1b[0m');
|
||||||
|
return this.$init(str);
|
||||||
|
};
|
||||||
|
} catch (err) {
|
||||||
|
//console.log('\x1b[36m[-] SSLPeerUnverifiedException not found\x1b[0m');
|
||||||
|
//console.log('\x1b[36m'+err+'\x1b[0m');
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
}, 0);
|
32
code/liblog.so原生日志输出.js
Normal file
32
code/liblog.so原生日志输出.js
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
function native_log(type,tag,msg){
|
||||||
|
var tag_new = Memory.allocUtf8String(tag)
|
||||||
|
var msg_new = Memory.allocUtf8String(msg)
|
||||||
|
var param_type_list = ["int","pointer","pointer","..."]
|
||||||
|
var print_ptr = Module.getExportByName("liblog.so","__android_log_print")
|
||||||
|
const print = new NativeFunction(print_ptr, 'int', param_type_list)
|
||||||
|
print(type,tag_new,msg_new)
|
||||||
|
}
|
||||||
|
|
||||||
|
function logv(tag,msg){
|
||||||
|
native_log(2,tag,msg)
|
||||||
|
}
|
||||||
|
|
||||||
|
function logd(tag,msg){
|
||||||
|
native_log(3,tag,msg)
|
||||||
|
}
|
||||||
|
|
||||||
|
function logi(tag,msg){
|
||||||
|
native_log(4,tag,msg)
|
||||||
|
}
|
||||||
|
|
||||||
|
function logw(tag,msg){
|
||||||
|
native_log(5,tag,msg)
|
||||||
|
}
|
||||||
|
|
||||||
|
function loge(tag,msg){
|
||||||
|
native_log(6,tag,msg)
|
||||||
|
}
|
||||||
|
|
||||||
|
function logf(tag,msg){
|
||||||
|
native_log(7,tag,msg)
|
||||||
|
}
|
17
code/network-security-config-bypass.js
Normal file
17
code/network-security-config-bypass.js
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
// frida -U -l network-security-config-bypass.js --no-pause -f your.package.name
|
||||||
|
Java.perform(function() {
|
||||||
|
NetworkSecurityConfig_Builder = Java.use("android.security.net.config.NetworkSecurityConfig$Builder")
|
||||||
|
CertificatesEntryRef = Java.use("android.security.net.config.CertificatesEntryRef")
|
||||||
|
CertificateSource = Java.use("android.security.net.config.CertificateSource")
|
||||||
|
UserCertificateSource = Java.use("android.security.net.config.UserCertificateSource")
|
||||||
|
|
||||||
|
NetworkSecurityConfig_Builder.getEffectiveCertificatesEntryRefs.implementation = function() {
|
||||||
|
origin = this.getEffectiveCertificatesEntryRefs()
|
||||||
|
|
||||||
|
source = UserCertificateSource.getInstance()
|
||||||
|
userCert = CertificatesEntryRef.$new(source, true)
|
||||||
|
origin.add(userCert)
|
||||||
|
|
||||||
|
return origin
|
||||||
|
}
|
||||||
|
})
|
23
code/okhttp proxy installator.js
Normal file
23
code/okhttp proxy installator.js
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
setTimeout(function() {
|
||||||
|
Java.perform(function() {
|
||||||
|
console.log('')
|
||||||
|
console.log("# OkHTTP proxy");
|
||||||
|
var OkHttpClient = Java.use("okhttp3.OkHttpClient");
|
||||||
|
var OkHttpBuilder = Java.use("okhttp3.OkHttpClient$Builder");
|
||||||
|
var Proxy = Java.use("java.net.Proxy");
|
||||||
|
var ProxyType = Java.use("java.net.Proxy$Type");
|
||||||
|
var InetSocketAddress = Java.use("java.net.InetSocketAddress");
|
||||||
|
|
||||||
|
var proxy = Proxy.$new(ProxyType.HTTP.value, InetSocketAddress.createUnresolved("1.2.3.4", 5678));
|
||||||
|
|
||||||
|
OkHttpClient.newBuilder.overload().implementation = function() {
|
||||||
|
return OkHttpBuilder.$new();
|
||||||
|
}
|
||||||
|
OkHttpBuilder.build.overload().implementation = function() {
|
||||||
|
console.log('[+] Installing proxy');
|
||||||
|
this.proxy(proxy);
|
||||||
|
return this.build();
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
}, 0)
|
63
code/okhttp3-pinning-bypass.js
Normal file
63
code/okhttp3-pinning-bypass.js
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
/*
|
||||||
|
* Description: OkHttp3 various SSL Pinning bypasses, including versions 4.2+.
|
||||||
|
* Authors: @apps3c and @pcipolloni
|
||||||
|
*/
|
||||||
|
|
||||||
|
setTimeout(function() {
|
||||||
|
|
||||||
|
Java.perform(function () {
|
||||||
|
|
||||||
|
var okhttp3_CertificatePinner_class = null;
|
||||||
|
try {
|
||||||
|
okhttp3_CertificatePinner_class = Java.use('okhttp3.CertificatePinner');
|
||||||
|
} catch (err) {
|
||||||
|
console.log('[-] OkHTTPv3 CertificatePinner class not found. Skipping.');
|
||||||
|
okhttp3_CertificatePinner_class = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(okhttp3_CertificatePinner_class != null) {
|
||||||
|
|
||||||
|
try{
|
||||||
|
okhttp3_CertificatePinner_class.check.overload('java.lang.String', 'java.util.List').implementation = function (str,list) {
|
||||||
|
console.log('[+] Bypassing OkHTTPv3 1: ' + str);
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
console.log('[+] Loaded OkHTTPv3 hook 1');
|
||||||
|
} catch(err) {
|
||||||
|
console.log('[-] Skipping OkHTTPv3 hook 1');
|
||||||
|
}
|
||||||
|
|
||||||
|
try{
|
||||||
|
okhttp3_CertificatePinner_class.check.overload('java.lang.String', 'java.security.cert.Certificate').implementation = function (str,cert) {
|
||||||
|
console.log('[+] Bypassing OkHTTPv3 2: ' + str);
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
console.log('[+] Loaded OkHTTPv3 hook 2');
|
||||||
|
} catch(err) {
|
||||||
|
console.log('[-] Skipping OkHTTPv3 hook 2');
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
okhttp3_CertificatePinner_class.check.overload('java.lang.String', '[Ljava.security.cert.Certificate;').implementation = function (str,cert_array) {
|
||||||
|
console.log('[+] Bypassing OkHTTPv3 3: ' + str);
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
console.log('[+] Loaded OkHTTPv3 hook 3');
|
||||||
|
} catch(err) {
|
||||||
|
console.log('[-] Skipping OkHTTPv3 hook 3');
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
okhttp3_CertificatePinner_class['check$okhttp'].implementation = function (str,obj) {
|
||||||
|
console.log('[+] Bypassing OkHTTPv3 4 (4.2+): ' + str);
|
||||||
|
};
|
||||||
|
console.log('[+] Loaded OkHTTPv3 hook 4 (4.2+)');
|
||||||
|
} catch(err) {
|
||||||
|
console.log('[-] Skipping OkHTTPv3 hook 4 (4.2+)');
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
}, 0);
|
16
code/uiwebview-ssl-validation-killer.js
Normal file
16
code/uiwebview-ssl-validation-killer.js
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
function killUIWebViewSSL() {
|
||||||
|
Interceptor.attach(ObjC.classes.UIWebView["- webView:resource:canAuthenticateAgainstProtectionSpace:forDataSource:"].implementation, {
|
||||||
|
onLeave: function(retval) {
|
||||||
|
retval.replace(ptr('0x1'));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
Interceptor.attach(ObjC.classes.UIWebView["- webView:resource:didReceiveAuthenticationChallenge:fromDataSource:"].implementation, {
|
||||||
|
onEnter: function(args) {
|
||||||
|
const chall = new ObjC.Object(args[4]);
|
||||||
|
const sender = chall.sender();
|
||||||
|
const cred = ObjC.classes.NSURLCredential.credentialForTrust_(chall.protectionSpace().serverTrust());
|
||||||
|
sender.useCredential_forAuthenticationChallenge_(cred, chall);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
66
code/universal-android-ssl-pinning-bypass-with-frida.js
Normal file
66
code/universal-android-ssl-pinning-bypass-with-frida.js
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
/*
|
||||||
|
Android SSL Re-pinning frida script v0.2 030417-pier
|
||||||
|
|
||||||
|
$ adb push burpca-cert-der.crt /data/local/tmp/cert-der.crt
|
||||||
|
$ frida -U -f it.app.mobile -l frida-android-repinning.js --no-pause
|
||||||
|
|
||||||
|
https://techblog.mediaservice.net/2017/07/universal-android-ssl-pinning-bypass-with-frida/
|
||||||
|
|
||||||
|
UPDATE 20191605: Fixed undeclared var. Thanks to @oleavr and @ehsanpc9999 !
|
||||||
|
*/
|
||||||
|
|
||||||
|
setTimeout(function(){
|
||||||
|
Java.perform(function (){
|
||||||
|
console.log("");
|
||||||
|
console.log("[.] Cert Pinning Bypass/Re-Pinning");
|
||||||
|
|
||||||
|
var CertificateFactory = Java.use("java.security.cert.CertificateFactory");
|
||||||
|
var FileInputStream = Java.use("java.io.FileInputStream");
|
||||||
|
var BufferedInputStream = Java.use("java.io.BufferedInputStream");
|
||||||
|
var X509Certificate = Java.use("java.security.cert.X509Certificate");
|
||||||
|
var KeyStore = Java.use("java.security.KeyStore");
|
||||||
|
var TrustManagerFactory = Java.use("javax.net.ssl.TrustManagerFactory");
|
||||||
|
var SSLContext = Java.use("javax.net.ssl.SSLContext");
|
||||||
|
|
||||||
|
// Load CAs from an InputStream
|
||||||
|
console.log("[+] Loading our CA...")
|
||||||
|
var cf = CertificateFactory.getInstance("X.509");
|
||||||
|
|
||||||
|
try {
|
||||||
|
var fileInputStream = FileInputStream.$new("/data/local/tmp/cert-der.crt");
|
||||||
|
}
|
||||||
|
catch(err) {
|
||||||
|
console.log("[o] " + err);
|
||||||
|
}
|
||||||
|
|
||||||
|
var bufferedInputStream = BufferedInputStream.$new(fileInputStream);
|
||||||
|
var ca = cf.generateCertificate(bufferedInputStream);
|
||||||
|
bufferedInputStream.close();
|
||||||
|
|
||||||
|
var certInfo = Java.cast(ca, X509Certificate);
|
||||||
|
console.log("[o] Our CA Info: " + certInfo.getSubjectDN());
|
||||||
|
|
||||||
|
// Create a KeyStore containing our trusted CAs
|
||||||
|
console.log("[+] Creating a KeyStore for our CA...");
|
||||||
|
var keyStoreType = KeyStore.getDefaultType();
|
||||||
|
var keyStore = KeyStore.getInstance(keyStoreType);
|
||||||
|
keyStore.load(null, null);
|
||||||
|
keyStore.setCertificateEntry("ca", ca);
|
||||||
|
|
||||||
|
// Create a TrustManager that trusts the CAs in our KeyStore
|
||||||
|
console.log("[+] Creating a TrustManager that trusts the CA in our KeyStore...");
|
||||||
|
var tmfAlgorithm = TrustManagerFactory.getDefaultAlgorithm();
|
||||||
|
var tmf = TrustManagerFactory.getInstance(tmfAlgorithm);
|
||||||
|
tmf.init(keyStore);
|
||||||
|
console.log("[+] Our TrustManager is ready...");
|
||||||
|
|
||||||
|
console.log("[+] Hijacking SSLContext methods now...")
|
||||||
|
console.log("[-] Waiting for the app to invoke SSLContext.init()...")
|
||||||
|
|
||||||
|
SSLContext.init.overload("[Ljavax.net.ssl.KeyManager;", "[Ljavax.net.ssl.TrustManager;", "java.security.SecureRandom").implementation = function(a,b,c) {
|
||||||
|
console.log("[o] App invoked javax.net.ssl.SSLContext.init...");
|
||||||
|
SSLContext.init.overload("[Ljavax.net.ssl.KeyManager;", "[Ljavax.net.ssl.TrustManager;", "java.security.SecureRandom").call(this, a, tmf.getTrustManagers(), c);
|
||||||
|
console.log("[+] SSLContext initialized with our custom TrustManager!");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},0);
|
Loading…
Reference in New Issue
Block a user