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 _) {
}
}
}