/*----------------------------------------------------------------------------+
*| |
*| Android's Hooker |
*| |
*+---------------------------------------------------------------------------+
*| Copyright (C) 2011 Georges Bossert and Dimitri Kirchner |
*| This program is free software: you can redistribute it and/or modify |
*| it under the terms of the GNU General Public License as published by |
*| the Free Software Foundation, either version 3 of the License, or |
*| (at your option) any later version. |
*| |
*| This program is distributed in the hope that it will be useful, |
*| but WITHOUT ANY WARRANTY; without even the implied warranty of |
*| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
*| GNU General Public License for more details. |
*| |
*| You should have received a copy of the GNU General Public License |
*| along with this program. If not, see <http://www.gnu.org/licenses/>. |
*+---------------------------------------------------------------------------+
*| @url : http://www.amossys.fr |
*| @contact : android-hooker@amossys.fr |
*| @sponsors : Amossys, http://www.amossys.fr |
*+---------------------------------------------------------------------------+
*/
package com.amossys.hooker.hookers;
import java.util.HashMap;
import java.util.Map;
import com.amossys.hooker.SubstrateMain;
import com.amossys.hooker.exceptions.HookerInitializationException;
/**
* Hooks for Contents data which is permitted by ContentProvider and ContentResolver classes.
* @author Dimitri Kirchner
*
*/
public class ContentsDataHooker extends Hooker {
/**
* Name of the hooker
*/
private static final String NAME_HOOKER = "ContentsData";
/**
* @param name
*/
public ContentsDataHooker() {
super(NAME_HOOKER);
}
/*
* (non-Javadoc)
*
* @see com.amossys.hooker.hookers.Hooker#attach()
*/
@Override
public void attach() {
this.attachOnContentProviderClass();
this.attachOnContentResolverClass();
this.attachOnCursorWrapperClass();
this.attachOnSQLiteCursorClass();
this.attachOnContextWrapperClass();
}
/**
* Hook calls to specific methods of the ContentProvider class.
* Do NOT hook methods query/insert/delete/update since they are abstract.
*/
private void attachOnContentProviderClass() {
Map<String, Integer> methodsFromLocationToHook = new HashMap<String, Integer>();
methodsFromLocationToHook.put("applyBatch", 2);
methodsFromLocationToHook.put("bulkInsert", 2);
methodsFromLocationToHook.put("call", 2);
methodsFromLocationToHook.put("dump", 1);
methodsFromLocationToHook.put("getWritePermission", 0);
methodsFromLocationToHook.put("getReadPermission", 0);
methodsFromLocationToHook.put("getPathPermissions", 0);
methodsFromLocationToHook.put("openAssetFile", 1);
methodsFromLocationToHook.put("openFile", 1);
methodsFromLocationToHook.put("openPipeHelper", 1);
methodsFromLocationToHook.put("openTypedAssetFile", 1);
//These methods are protected.
// methodsFromLocationToHook.put("setPathPermissions", 2);
// methodsFromLocationToHook.put("setReadPermission", 2);
// methodsFromLocationToHook.put("setWritePermission", 2);
try {
hookMethods(null, "android.content.ContentProvider",
methodsFromLocationToHook);
SubstrateMain.log("hooking android.content.ContentProvider methods sucessful");
} catch (HookerInitializationException e) {
SubstrateMain.log("hooking android.content.ContentProvider methods has failed", e);
}
}
/**
* Hook calls to specific methods of the ContentResolver class
*/
private void attachOnContentResolverClass() {
Map<String, Integer> methodsFromLocationToHook = new HashMap<String, Integer>();
methodsFromLocationToHook.put("acquireContentProviderClient", 0);
methodsFromLocationToHook.put("acquireUnstableContentProviderClient", 0);
methodsFromLocationToHook.put("addPeriodicSync", 0);
methodsFromLocationToHook.put("applyBatch", 2);
methodsFromLocationToHook.put("call", 1);
methodsFromLocationToHook.put("delete", 2);
methodsFromLocationToHook.put("getStreamTypes", 0);
methodsFromLocationToHook.put("getType", 0);
methodsFromLocationToHook.put("insert", 2);
methodsFromLocationToHook.put("notifyChange", 1);
methodsFromLocationToHook.put("openAssetFileDescriptor", 1);
methodsFromLocationToHook.put("openFileDescriptor", 1);
methodsFromLocationToHook.put("openInputStream", 1);
methodsFromLocationToHook.put("openOutputStream", 2);
methodsFromLocationToHook.put("openTypedAssetFileDescriptor", 1);
methodsFromLocationToHook.put("query", 1);
methodsFromLocationToHook.put("registerContentObserver", 2);
methodsFromLocationToHook.put("requestSync", 0);
methodsFromLocationToHook.put("unregisterContentObserver", 2);
methodsFromLocationToHook.put("update", 2);
try {
hookMethods(null, "android.content.ContentResolver",
methodsFromLocationToHook);
SubstrateMain.log("hooking android.content.ContentResolver methods sucessful");
} catch (HookerInitializationException e) {
SubstrateMain.log("hooking android.content.ContentResolver methods has failed", e);
}
}
/**
* Attach on CursorWrapper class.
*/
private void attachOnCursorWrapperClass () {
Map<String, Integer> methodsFromLocationToHook = new HashMap<String, Integer>();
methodsFromLocationToHook.put("close", 1);
methodsFromLocationToHook.put("copyStringToBuffer", 2);
methodsFromLocationToHook.put("getBlob", 0);
methodsFromLocationToHook.put("getColumnCount", 0);
methodsFromLocationToHook.put("getColumnIndex", 0);
methodsFromLocationToHook.put("getColumnIndexOrThrow", 0);
methodsFromLocationToHook.put("getColumnName", 0);
methodsFromLocationToHook.put("getColumnNames", 0);
methodsFromLocationToHook.put("getPosition", 0);
methodsFromLocationToHook.put("getString", 0);
methodsFromLocationToHook.put("registerContentObserver", 2);
methodsFromLocationToHook.put("registerDataSetObserver", 2);
methodsFromLocationToHook.put("requery", 1);
methodsFromLocationToHook.put("respond", 1);
methodsFromLocationToHook.put("setNotificationUri", 2);
methodsFromLocationToHook.put("unregisterContentObserver", 2);
try {
hookMethods(null, "android.database.CursorWrapper",
methodsFromLocationToHook);
SubstrateMain.log("hooking android.database.CursorWrapper methods sucessful");
} catch (HookerInitializationException e) {
SubstrateMain.log("hooking android.database.CursorWrapper methods has failed", e);
}
}
/**
* Attach on CursorWrapper class.
*/
private void attachOnSQLiteCursorClass () {
Map<String, Integer> methodsFromLocationToHook = new HashMap<String, Integer>();
methodsFromLocationToHook.put("close", 1);
methodsFromLocationToHook.put("getColumnIndex", 1);
methodsFromLocationToHook.put("getColumnNames", 1);
methodsFromLocationToHook.put("getCount", 0);
methodsFromLocationToHook.put("getDatabase", 1);
methodsFromLocationToHook.put("onMove", 0);
methodsFromLocationToHook.put("setSelectionArguments", 2);
methodsFromLocationToHook.put("setWindow", 1);
try {
hookMethods(null, "android.database.sqlite.SQLiteCursor",
methodsFromLocationToHook);
SubstrateMain.log("hooking android.database.sqlite.SQLiteCursor methods sucessful");
} catch (HookerInitializationException e) {
SubstrateMain.log("hooking android.database.sqlite.SQLiteCursor methods has failed", e);
}
}
private void attachOnContextWrapperClass() {
Map<String, Integer> methodsFromLocationToHook = new HashMap<String, Integer>();
methodsFromLocationToHook.put("getContentResolver", 1);
try {
hookMethods(null, "android.content.ContextWrapper",
methodsFromLocationToHook);
SubstrateMain.log("hooking android.content.ContextWrapper methods sucessful");
} catch (HookerInitializationException e) {
SubstrateMain.log("hooking android.content.ContextWrapper methods has failed", e);
}
}
}