/*----------------------------------------------------------------------------+ *| | *| 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); } } }