package mobi.acpm.inspeckage.hooks; import android.app.Activity; import android.content.ContentValues; import android.content.ContextWrapper; import android.database.Cursor; import android.database.sqlite.SQLiteDatabase; import android.net.Uri; import android.util.Base64; import java.io.File; import java.util.Map; import java.util.Set; import de.robv.android.xposed.XC_MethodHook; import de.robv.android.xposed.XposedBridge; import de.robv.android.xposed.XposedHelpers; import de.robv.android.xposed.callbacks.XC_LoadPackage; import static de.robv.android.xposed.XposedHelpers.findAndHookMethod; /** * Created by acpm on 21/11/15. */ public class SQLiteHook extends XC_MethodHook { public static final String TAG = "Inspeckage_SQLite:"; public static void initAllHooks(final XC_LoadPackage.LoadPackageParam loadPackageParam) { findAndHookMethod(SQLiteDatabase.class, "execSQL", String.class, new XC_MethodHook() { protected void afterHookedMethod(MethodHookParam param) throws Throwable { XposedBridge.log(TAG + "execSQL(" + param.args[0] + ")"); } }); findAndHookMethod(SQLiteDatabase.class, "execSQL", String.class, Object[].class, new XC_MethodHook() { protected void afterHookedMethod(MethodHookParam param) throws Throwable { Object[] obj = (Object[]) param.args[1]; int obj_c = 0; if (obj != null && obj.length > 0) { obj_c = obj.length; } XposedBridge.log(TAG + "execSQL(" + param.args[0] + ") with " + String.valueOf(obj_c) + " args."); } }); findAndHookMethod(SQLiteDatabase.class, "update", String.class, ContentValues.class, String.class, String[].class, new XC_MethodHook() { protected void afterHookedMethod(MethodHookParam param) throws Throwable { SQLiteDatabase sqlitedb = (SQLiteDatabase) param.thisObject; ContentValues contentValues = (ContentValues) param.args[1]; StringBuffer sb = new StringBuffer(); Set<Map.Entry<String, Object>> s = contentValues.valueSet(); for (Map.Entry<String, Object> entry : s) { sb.append(entry.getKey() + "=" + String.valueOf(entry.getValue()) + ","); } StringBuffer sbuff = new StringBuffer(); if (param.args[3] != null) { for (String str : (String[]) param.args[3]) { sbuff.append(str + ","); } } String set = ""; if (sb.toString().length() > 1) { set = sb.toString().substring(0, sb.length() - 1); } String whereArgs = ""; if (sbuff.toString().length() > 1) { whereArgs = sbuff.toString().substring(0, sbuff.length() - 1); } XposedBridge.log(TAG + "\nUPDATE " + param.args[0] + " SET " + set + "" + " WHERE " + param.args[2] + "" + whereArgs); } }); //1 INSERT INTO students VALUES(grade=Teste2,name=Teste1) findAndHookMethod(SQLiteDatabase.class, "insert", String.class, String.class, ContentValues.class, new XC_MethodHook() { protected void afterHookedMethod(MethodHookParam param) throws Throwable { SQLiteDatabase sqlitedb = (SQLiteDatabase) param.thisObject; ContentValues contentValues = (ContentValues) param.args[2]; StringBuffer sb = new StringBuffer(); for (Map.Entry<String, Object> entry : contentValues.valueSet()) { sb.append(entry.getKey() + "=" + String.valueOf(entry.getValue()) + ","); } XposedBridge.log(TAG + "INSERT INTO " + param.args[0] + " VALUES(" + sb.toString().substring(0, sb.length() - 1) + ")"); } }); findAndHookMethod(Activity.class, "managedQuery", Uri.class, String[].class, String.class, String[].class, String.class, new XC_MethodHook() { protected void afterHookedMethod(MethodHookParam param) throws Throwable { Uri uri = (Uri) param.args[0]; StringBuffer projection = new StringBuffer(); if (param.args[1] != null) { for (String str : (String[]) param.args[1]) { projection.append(str + ","); } } String selection = ""; if (param.args[2] != null) { selection = " WHERE " + (String) param.args[2] + " = "; } StringBuffer selectionArgs = new StringBuffer(); if (param.args[3] != null) { for (String str : (String[]) param.args[3]) { selectionArgs.append(str + ","); } } String sortOrder = ""; if (param.args[4] != null) { sortOrder = " ORDER BY " + (String) param.args[4]; } String projec = ""; if (projection.toString().equals("")) { projec = "*";//projection.append("*"); } else { projec = projection.toString().substring(0, projection.length() - 1); } Cursor cursor = (Cursor) param.getResult(); StringBuffer result = new StringBuffer(); if (cursor != null) if (cursor.moveToFirst()) { do { int x = cursor.getColumnCount(); StringBuffer sb = new StringBuffer(); for (int i = 0; i < x; i++) { if (cursor.getType(i) == Cursor.FIELD_TYPE_BLOB) { String blob = Base64.encodeToString(cursor.getBlob(i), Base64.NO_WRAP); sb.append(cursor.getColumnName(i) + "=" + blob + ","); } else { sb.append(cursor.getColumnName(i) + "=" + cursor.getString(i) + ","); } } result.append(sb.toString().substring(0, sb.length() - 1) + "\n"); } while (cursor.moveToNext()); } XposedBridge.log(TAG + "SELECT " + projec + " FROM " + uri.getAuthority() + uri.getPath() + selection + selectionArgs.toString() + sortOrder + "\n [" + result.toString() + "]"); } }); //query findAndHookMethod(SQLiteDatabase.class, "query", String.class, String[].class, String.class, String[].class, String.class, String.class, String.class, String.class, new XC_MethodHook() { protected void afterHookedMethod(MethodHookParam param) throws Throwable { String table = (String) param.args[0]; String[] columns = (String[]) param.args[1]; String having = (String) param.args[5]; String limit = (String) param.args[6]; StringBuffer csb = new StringBuffer(); if (param.args[1] != null) { for (String str : (String[]) param.args[1]) { csb.append(str + ","); } } String selection = ""; if (param.args[2] != null) { selection = " WHERE " + (String) param.args[2] + " = "; } StringBuffer selectionArgs = new StringBuffer(); if (param.args[3] != null) { for (String str : (String[]) param.args[3]) { selectionArgs.append(str + ","); } } String groupBy = ""; if (param.args[4] != null) { groupBy = " GROUP BY " + (String) param.args[4]; } String sortOrder = ""; if (param.args[6] != null) { sortOrder = " ORDER BY " + (String) param.args[6]; } if (csb.toString().equals("")) { csb.append("*"); } Cursor cursor = (Cursor) param.getResult(); StringBuffer result = new StringBuffer(); if (cursor != null) if (cursor.moveToFirst()) { do { int x = cursor.getColumnCount(); StringBuffer sb = new StringBuffer(); for (int i = 0; i < x; i++) { if(cursor.getType(i) == Cursor.FIELD_TYPE_BLOB){ String blob = Base64.encodeToString(cursor.getBlob(i), Base64.NO_WRAP); sb.append(cursor.getColumnName(i) + "=" + blob + ","); }else { sb.append(cursor.getColumnName(i) + "=" + cursor.getString(i) + ","); } } result.append(sb.toString().substring(0, sb.length() - 1) + "\n"); } while (cursor.moveToNext()); } XposedBridge.log(TAG + "SELECT " + csb.toString() + " FROM " + table + selection + selectionArgs.toString() + sortOrder + "\n" + result.toString() + ""); } }); findAndHookMethod(ContextWrapper.class, "getDatabasePath", String.class, new XC_MethodHook() { protected void afterHookedMethod(MethodHookParam param) throws Throwable { XposedBridge.log(TAG + "[Context] getDatabasePath(" + param.args[0] + ")"); } }); ///SQLCipher try { findAndHookMethod("net.sqlcipher.database.SQLiteDatabase", loadPackageParam.classLoader, "execSQL", String.class, new XC_MethodHook() { protected void afterHookedMethod(MethodHookParam param) throws Throwable { XposedBridge.log(TAG + "[SQLCipher] execSQL(" + param.args[0] + ")"); } }); findAndHookMethod("net.sqlcipher.database.SQLiteDatabase", loadPackageParam.classLoader, "execSQL", String.class, Object[].class, new XC_MethodHook() { protected void afterHookedMethod(MethodHookParam param) throws Throwable { Object[] obj = (Object[]) param.args[1]; int obj_c = 0; if (obj != null && obj.length > 0) { obj_c = obj.length; } XposedBridge.log(TAG + "[SQLCipher] execSQL(" + param.args[0] + ") with " + String.valueOf(obj_c) + " args."); } }); findAndHookMethod("net.sqlcipher.database.SQLiteDatabase", loadPackageParam.classLoader, "openOrCreateDatabase", File.class, String.class, "net.sqlcipher.database.SQLiteDatabase.CursorFactory", new XC_MethodHook() { protected void afterHookedMethod(MethodHookParam param) throws Throwable { File f = (File) param.args[0]; String passwd = (String) param.args[1]; XposedBridge.log(TAG + "[SQLCipher] Open or Create:" + f.getName() + " with password: " + passwd); } }); findAndHookMethod("net.sqlcipher.database.SQLiteDatabase", loadPackageParam.classLoader, "rawQuery", String.class, String[].class, new XC_MethodHook() { protected void afterHookedMethod(MethodHookParam param) throws Throwable { String[] obj = (String[]) param.args[1]; int obj_c = 0; if (obj != null && obj.length > 0) { obj_c = obj.length; } XposedBridge.log(TAG + "[SQLCipher] rawQuery(" + param.args[0] + ") with " + String.valueOf(obj_c) + " args."); } }); } catch (XposedHelpers.ClassNotFoundError _) { } catch (NoSuchMethodError _) { } } }