├── .classpath ├── .gitignore ├── .project ├── AndroidManifest.xml ├── README.md ├── ic_launcher-web.png ├── libs ├── android-support-v4.jar ├── ddmlib.jar ├── substrate-api.jar └── substrate-bless.jar ├── proguard-project.txt ├── project.properties ├── res ├── drawable-hdpi │ └── ic_launcher.png ├── drawable-mdpi │ └── ic_launcher.png ├── drawable-xhdpi │ └── ic_launcher.png ├── drawable-xxhdpi │ └── ic_launcher.png ├── layout │ └── activity_test.xml ├── menu │ └── test.xml ├── values-v11 │ └── styles.xml ├── values-v14 │ └── styles.xml ├── values-w820dp │ └── dimens.xml └── values │ ├── dimens.xml │ ├── strings.xml │ └── styles.xml ├── src └── com │ └── shuwoom │ └── apihooker │ ├── ApplicationConfig.java │ ├── GlobalContextHooker.java │ ├── SubstrateMain.java │ ├── TestActivity.java │ ├── common │ ├── Config.java │ ├── DataChanger.java │ ├── DataWatcher.java │ └── InterceptEvent.java │ ├── hookers │ ├── Hooker.java │ ├── NetworkHooker.java │ └── interfaces │ │ └── HookerListener.java │ └── services │ └── ReceiverService.java └── test_pic ├── activity_show.png └── logcat.png /.classpath: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | lt application files 2 | *.apk 3 | *.ap_ 4 | 5 | # Files for the Dalvik VM 6 | *.dex 7 | 8 | # Java class files 9 | *.class 10 | 11 | # Generated files 12 | bin/ 13 | gen/ 14 | 15 | # Gradle files 16 | .gradle/ 17 | build/ 18 | 19 | # Local configuration file (sdk path, etc) 20 | local.properties 21 | 22 | # Proguard folder generated by Eclipse 23 | proguard/ 24 | 25 | # Log Files 26 | *.log 27 | -------------------------------------------------------------------------------- /.project: -------------------------------------------------------------------------------- 1 | 2 | 3 | AndroidAPIHooker 4 | 5 | 6 | 7 | 8 | 9 | com.android.ide.eclipse.adt.ResourceManagerBuilder 10 | 11 | 12 | 13 | 14 | com.android.ide.eclipse.adt.PreCompilerBuilder 15 | 16 | 17 | 18 | 19 | org.eclipse.jdt.core.javabuilder 20 | 21 | 22 | 23 | 24 | com.android.ide.eclipse.adt.ApkBuilder 25 | 26 | 27 | 28 | 29 | 30 | com.android.ide.eclipse.adt.AndroidNature 31 | org.eclipse.jdt.core.javanature 32 | 33 | 34 | -------------------------------------------------------------------------------- /AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 10 | 11 | 12 | 13 | 14 | 17 | 18 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # AndroidAPIHooker 2 | master分支停止更新,最新代码在v2.0分支。 3 | 4 | ![image](https://github.com/guanchao/AndroidAPIHooker/raw/master/test_pic/activity_show.png) 5 | 6 | 7 | ![image](https://github.com/guanchao/AndroidAPIHooker/raw/master/test_pic/logcat.png) 8 | -------------------------------------------------------------------------------- /ic_launcher-web.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/guanchao/AndroidAPIHooker/3cf38b2e3ca49e75831067675beb4b740e316b00/ic_launcher-web.png -------------------------------------------------------------------------------- /libs/android-support-v4.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/guanchao/AndroidAPIHooker/3cf38b2e3ca49e75831067675beb4b740e316b00/libs/android-support-v4.jar -------------------------------------------------------------------------------- /libs/ddmlib.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/guanchao/AndroidAPIHooker/3cf38b2e3ca49e75831067675beb4b740e316b00/libs/ddmlib.jar -------------------------------------------------------------------------------- /libs/substrate-api.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/guanchao/AndroidAPIHooker/3cf38b2e3ca49e75831067675beb4b740e316b00/libs/substrate-api.jar -------------------------------------------------------------------------------- /libs/substrate-bless.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/guanchao/AndroidAPIHooker/3cf38b2e3ca49e75831067675beb4b740e316b00/libs/substrate-bless.jar -------------------------------------------------------------------------------- /proguard-project.txt: -------------------------------------------------------------------------------- 1 | # To enable ProGuard in your project, edit project.properties 2 | # to define the proguard.config property as described in that file. 3 | # 4 | # Add project specific ProGuard rules here. 5 | # By default, the flags in this file are appended to flags specified 6 | # in ${sdk.dir}/tools/proguard/proguard-android.txt 7 | # You can edit the include path and order by changing the ProGuard 8 | # include property in project.properties. 9 | # 10 | # For more details, see 11 | # http://developer.android.com/guide/developing/tools/proguard.html 12 | 13 | # Add any project specific keep options here: 14 | 15 | # If your project uses WebView with JS, uncomment the following 16 | # and specify the fully qualified class name to the JavaScript interface 17 | # class: 18 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 19 | # public *; 20 | #} 21 | -------------------------------------------------------------------------------- /project.properties: -------------------------------------------------------------------------------- 1 | # This file is automatically generated by Android Tools. 2 | # Do not modify this file -- YOUR CHANGES WILL BE ERASED! 3 | # 4 | # This file must be checked in Version Control Systems. 5 | # 6 | # To customize properties used by the Ant build system edit 7 | # "ant.properties", and override values to adapt the script to your 8 | # project structure. 9 | # 10 | # To enable ProGuard to shrink and obfuscate your code, uncomment this (available properties: sdk.dir, user.home): 11 | #proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt 12 | 13 | # Project target. 14 | target=android-22 15 | -------------------------------------------------------------------------------- /res/drawable-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/guanchao/AndroidAPIHooker/3cf38b2e3ca49e75831067675beb4b740e316b00/res/drawable-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /res/drawable-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/guanchao/AndroidAPIHooker/3cf38b2e3ca49e75831067675beb4b740e316b00/res/drawable-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /res/drawable-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/guanchao/AndroidAPIHooker/3cf38b2e3ca49e75831067675beb4b740e316b00/res/drawable-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /res/drawable-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/guanchao/AndroidAPIHooker/3cf38b2e3ca49e75831067675beb4b740e316b00/res/drawable-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /res/layout/activity_test.xml: -------------------------------------------------------------------------------- 1 | 10 | 11 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /res/menu/test.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /res/values-v11/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /res/values-v14/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 8 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /res/values-w820dp/dimens.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 8 | 64dp 9 | 10 | 11 | -------------------------------------------------------------------------------- /res/values/dimens.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 16dp 5 | 16dp 6 | 7 | 8 | -------------------------------------------------------------------------------- /res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | AndroidAPIHooker 5 | TestActivity 6 | Hello world! 7 | Settings 8 | 9 | 10 | -------------------------------------------------------------------------------- /res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 14 | 15 | 16 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /src/com/shuwoom/apihooker/ApplicationConfig.java: -------------------------------------------------------------------------------- 1 | package com.shuwoom.apihooker; 2 | 3 | import android.content.Context; 4 | 5 | public class ApplicationConfig { 6 | private static String packageName; 7 | private static Context context; 8 | 9 | public static String getPackageName() { 10 | return packageName; 11 | } 12 | 13 | public static void setPackageName(String packageName) { 14 | ApplicationConfig.packageName = packageName; 15 | } 16 | 17 | public static Context getContext() { 18 | return context; 19 | } 20 | 21 | public static void setContext(Context context) { 22 | ApplicationConfig.context = context; 23 | } 24 | 25 | } 26 | -------------------------------------------------------------------------------- /src/com/shuwoom/apihooker/GlobalContextHooker.java: -------------------------------------------------------------------------------- 1 | package com.shuwoom.apihooker; 2 | 3 | import java.lang.reflect.Method; 4 | import java.util.List; 5 | 6 | import android.content.Context; 7 | import android.util.Log; 8 | 9 | import com.saurik.substrate.MS; 10 | import com.shuwoom.apihooker.common.Config; 11 | 12 | public class GlobalContextHooker { 13 | 14 | public void hook(final List filteredPackageNames){ 15 | MS.hookClassLoad("android.app.ContextImpl", new MS.ClassLoadHook() { 16 | 17 | @SuppressWarnings("unchecked") 18 | @Override 19 | public void classLoaded(Class resources) { 20 | loadContext(resources, filteredPackageNames); 21 | } 22 | }); 23 | } 24 | 25 | @SuppressWarnings("unchecked") 26 | protected void loadContext(Class resources, final List filteredPackageNames) { 27 | Method getPackageNameMethod = null; 28 | try { 29 | getPackageNameMethod = resources.getMethod("getPackageName",new Class[] {}); 30 | } catch (NoSuchMethodException e1) { 31 | Log.v(Config.DEBUG_TAG, "3333333333" + e1); 32 | e1.printStackTrace(); 33 | } 34 | 35 | if (getPackageNameMethod == null) { 36 | return ; 37 | } 38 | 39 | final MS.MethodPointer oldPointer = new MS.MethodPointer(); 40 | MS.hookMethod(resources, getPackageNameMethod, new MS.MethodHook() { 41 | 42 | @Override 43 | public Object invoked(Object arg0, Object... arg1) throws Throwable { 44 | String packageName = (String) oldPointer.invoke(arg0, arg1); 45 | ApplicationConfig.setPackageName(packageName); 46 | 47 | if(filteredPackageNames.contains(packageName)){ 48 | return oldPointer.invoke(arg0, arg1); 49 | } 50 | try { 51 | Class contextImplClass = Class.forName("android.app.ContextImpl"); 52 | Class noparams[] = {}; 53 | Method getApplicationContextMethod = contextImplClass.getDeclaredMethod("getApplicationContext", noparams); 54 | 55 | Context context = (Context) getApplicationContextMethod.invoke(arg0); 56 | if(context != null){ 57 | ApplicationConfig.setContext(context); 58 | // Log.v(Config.DEBUG_TAG, "hook context from==>" + packageName ); 59 | } 60 | } catch (NoSuchMethodException e) { 61 | Log.v(Config.DEBUG_TAG, "error message==>" + e); 62 | e.printStackTrace(); 63 | } catch (ClassNotFoundException e) { 64 | Log.v(Config.DEBUG_TAG, "error message==>" + e); 65 | e.printStackTrace(); 66 | } catch(Exception e){ 67 | Log.v(Config.DEBUG_TAG, "error message==>" + e); 68 | e.printStackTrace(); 69 | } 70 | return oldPointer.invoke(arg0, arg1); 71 | } 72 | }, oldPointer); 73 | 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /src/com/shuwoom/apihooker/SubstrateMain.java: -------------------------------------------------------------------------------- 1 | package com.shuwoom.apihooker; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | 6 | import com.shuwoom.apihooker.hookers.NetworkHooker; 7 | 8 | public class SubstrateMain { 9 | //the packages below are ingonred 10 | public static final List FILTERED_PACKAGE_NAMES = new ArrayList(); 11 | 12 | static { 13 | FILTERED_PACKAGE_NAMES.add("android"); 14 | FILTERED_PACKAGE_NAMES.add("com.android.phone"); 15 | FILTERED_PACKAGE_NAMES.add("com.android.systemui"); 16 | FILTERED_PACKAGE_NAMES.add("com.android.settings"); 17 | FILTERED_PACKAGE_NAMES.add("com.android.inputmethod.latin"); 18 | FILTERED_PACKAGE_NAMES.add("com.android.launcher"); 19 | FILTERED_PACKAGE_NAMES.add("com.android.email"); 20 | FILTERED_PACKAGE_NAMES.add("com.android.deskclock"); 21 | FILTERED_PACKAGE_NAMES.add("com.android.mms"); 22 | FILTERED_PACKAGE_NAMES.add("com.android.calendar"); 23 | FILTERED_PACKAGE_NAMES.add("com.android.providers.downloads"); 24 | FILTERED_PACKAGE_NAMES.add("com.noshufou.android.su"); 25 | FILTERED_PACKAGE_NAMES.add("com.android.providers.calendar"); 26 | FILTERED_PACKAGE_NAMES.add("com.android.providers.settings"); 27 | FILTERED_PACKAGE_NAMES.add("com.android.contacts"); 28 | FILTERED_PACKAGE_NAMES.add("com.android.providers.contacts"); 29 | FILTERED_PACKAGE_NAMES.add("com.android.providers.userdictionary"); 30 | FILTERED_PACKAGE_NAMES.add("com.android.exchange"); 31 | FILTERED_PACKAGE_NAMES.add("com.android.providers.media"); 32 | FILTERED_PACKAGE_NAMES.add("com.android.browser"); 33 | FILTERED_PACKAGE_NAMES.add("com.android.quicksearchbox"); 34 | FILTERED_PACKAGE_NAMES.add("com.saurik.substrate"); 35 | FILTERED_PACKAGE_NAMES.add("com.shuwoom.apihooker"); 36 | } 37 | 38 | 39 | public static void initialize(){ 40 | new NetworkHooker().hook(); 41 | new GlobalContextHooker().hook(FILTERED_PACKAGE_NAMES); 42 | } 43 | 44 | } 45 | -------------------------------------------------------------------------------- /src/com/shuwoom/apihooker/TestActivity.java: -------------------------------------------------------------------------------- 1 | package com.shuwoom.apihooker; 2 | 3 | import android.app.Activity; 4 | import android.os.Bundle; 5 | import android.os.Messenger; 6 | import android.widget.TextView; 7 | 8 | import com.shuwoom.apihooker.common.DataChanger; 9 | import com.shuwoom.apihooker.common.DataWatcher; 10 | import com.shuwoom.apihooker.common.InterceptEvent; 11 | 12 | public class TestActivity extends Activity { 13 | 14 | private TextView eventText; 15 | private Messenger mService = null; 16 | private StringBuilder msg = new StringBuilder(); 17 | 18 | private DataWatcher dataWatcher = new DataWatcher() { 19 | 20 | @Override 21 | public void onDataChanged(InterceptEvent data) { 22 | if(eventText != null && data != null){ 23 | StringBuilder str = new StringBuilder(); 24 | str.append("HookerName : " + data.getHookerName() + "\n"); 25 | str.append("PackageName : " + data.getPackageName() + "\n"); 26 | str.append("MethodName : " + data.getMethodName() + "\n"); 27 | str.append("Timestamp : " + data.getTimestamp() + "\n"); 28 | str.append("Data : " + data.getData() + "\n\n"); 29 | msg.insert(0, str); 30 | eventText.setText(msg.toString()); 31 | } 32 | } 33 | }; 34 | 35 | 36 | @Override 37 | protected void onCreate(Bundle savedInstanceState) { 38 | super.onCreate(savedInstanceState); 39 | setContentView(R.layout.activity_test); 40 | 41 | eventText = (TextView) findViewById(R.id.event_text); 42 | 43 | } 44 | 45 | @Override 46 | protected void onResume() { 47 | super.onResume(); 48 | DataChanger.getInstance(this).addObserver(dataWatcher); 49 | } 50 | 51 | @Override 52 | protected void onPause() { 53 | super.onPause(); 54 | DataChanger.getInstance(this).deleteObserver(dataWatcher); 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /src/com/shuwoom/apihooker/common/Config.java: -------------------------------------------------------------------------------- 1 | package com.shuwoom.apihooker.common; 2 | 3 | public class Config { 4 | public static final String DEBUG_TAG = "api_hooker"; 5 | public static final String DEBUG_CONNECT_TAG = "connect_test"; 6 | public static final String DEBUG_ERROR = "api_hooker_error"; 7 | } 8 | -------------------------------------------------------------------------------- /src/com/shuwoom/apihooker/common/DataChanger.java: -------------------------------------------------------------------------------- 1 | package com.shuwoom.apihooker.common; 2 | 3 | import java.util.Observable; 4 | 5 | import android.content.Context; 6 | 7 | public class DataChanger extends Observable { 8 | private static DataChanger mInstance; 9 | private final Context context; 10 | 11 | private DataChanger(Context context) { 12 | this.context = context; 13 | } 14 | 15 | public synchronized static DataChanger getInstance(Context context) { 16 | if (mInstance == null) { 17 | mInstance = new DataChanger(context); 18 | } 19 | return mInstance; 20 | } 21 | 22 | public void update(InterceptEvent event) { 23 | setChanged(); 24 | notifyObservers(event); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/com/shuwoom/apihooker/common/DataWatcher.java: -------------------------------------------------------------------------------- 1 | package com.shuwoom.apihooker.common; 2 | 3 | import java.util.Observable; 4 | import java.util.Observer; 5 | 6 | public abstract class DataWatcher implements Observer{ 7 | 8 | @Override 9 | public void update(Observable observable, Object data) { 10 | if(data instanceof InterceptEvent){ 11 | onDataChanged((InterceptEvent) data); 12 | } 13 | } 14 | 15 | public abstract void onDataChanged(InterceptEvent downloadEntry); 16 | 17 | } 18 | -------------------------------------------------------------------------------- /src/com/shuwoom/apihooker/common/InterceptEvent.java: -------------------------------------------------------------------------------- 1 | package com.shuwoom.apihooker.common; 2 | 3 | import java.util.AbstractMap; 4 | import java.util.ArrayList; 5 | import java.util.Calendar; 6 | import java.util.HashMap; 7 | import java.util.List; 8 | import java.util.Map; 9 | import java.util.Map.Entry; 10 | import java.util.UUID; 11 | 12 | import org.json.JSONArray; 13 | import org.json.JSONException; 14 | import org.json.JSONObject; 15 | 16 | import android.os.Parcel; 17 | import android.os.Parcelable; 18 | 19 | public class InterceptEvent implements Parcelable { 20 | 21 | private UUID idEvent; 22 | 23 | private String IDXP; 24 | 25 | private long timestamp; 26 | 27 | private long relativeTimestamp; 28 | 29 | private String hookerName; 30 | //0:Nothing related personal info 31 | //1:Reading personal info 32 | //2:Writing personal info 33 | 34 | private int intrusiveLevel; 35 | 36 | private int instanceID; 37 | 38 | private String packageName; 39 | 40 | private String className; 41 | 42 | private String methodName; 43 | 44 | private List> parameters = new ArrayList>(); 45 | 46 | private Entry returns; 47 | 48 | private Map data = new HashMap(); 49 | 50 | 51 | 52 | public InterceptEvent(Parcel in) { 53 | idEvent = UUID.fromString(in.readString()); 54 | IDXP = in.readString(); 55 | timestamp = in.readLong(); 56 | relativeTimestamp = in.readLong(); 57 | hookerName = in.readString(); 58 | intrusiveLevel = in.readInt(); 59 | instanceID = in.readInt(); 60 | packageName = in.readString(); 61 | className = in.readString(); 62 | methodName = in.readString(); 63 | 64 | readParameterList(in); 65 | readReturnsEntry(in); 66 | readDataMap(in); 67 | 68 | } 69 | 70 | private void readDataMap(Parcel in) { 71 | int size = in.readInt(); 72 | if(size != 0){ 73 | for(int i = 0; i < size; i++){ 74 | String key = in.readString(); 75 | String value = in.readString(); 76 | data.put(key, value); 77 | } 78 | } 79 | } 80 | 81 | private void readReturnsEntry(Parcel in) { 82 | int tmp = in.readInt(); 83 | if(tmp != 0){ 84 | String key = in.readString(); 85 | String value = in.readString(); 86 | returns = new AbstractMap.SimpleEntry(key, value); 87 | } 88 | } 89 | 90 | private void readParameterList(Parcel in) { 91 | int size = in.readInt(); 92 | if(size != 0){ 93 | for(int i = 0; i < size; i++){ 94 | String key = in.readString(); 95 | String value = in.readString(); 96 | parameters.add(new AbstractMap.SimpleEntry(key, value)); 97 | } 98 | } 99 | } 100 | 101 | @Override 102 | public int describeContents() { 103 | // TODO Auto-generated method stub 104 | return 0; 105 | } 106 | 107 | @Override 108 | public void writeToParcel(Parcel dest, int flags) { 109 | dest.writeString(idEvent.toString()); 110 | dest.writeString(IDXP); 111 | dest.writeLong(timestamp); 112 | dest.writeLong(relativeTimestamp); 113 | dest.writeString(hookerName); 114 | dest.writeInt(intrusiveLevel); 115 | dest.writeInt(instanceID); 116 | dest.writeString(packageName); 117 | dest.writeString(className); 118 | dest.writeString(methodName); 119 | 120 | writeParametersList(dest); 121 | writeReturnsEntry(dest); 122 | writeDataMap(dest); 123 | } 124 | 125 | private void writeDataMap(Parcel dest) { 126 | if(parameters == null){ 127 | dest.writeInt(0); 128 | }else{ 129 | dest.writeInt(parameters.size()); 130 | for(Entry entry : parameters){ 131 | dest.writeString(entry.getKey()); 132 | dest.writeString(entry.getValue()); 133 | } 134 | } 135 | } 136 | 137 | private void writeReturnsEntry(Parcel dest) { 138 | if(returns == null){ 139 | dest.writeInt(0); 140 | }else{ 141 | dest.writeInt(1); 142 | dest.writeString(returns.getKey()); 143 | dest.writeString(returns.getValue()); 144 | } 145 | } 146 | 147 | private void writeParametersList(Parcel dest) { 148 | if(data == null){ 149 | dest.writeInt(0); 150 | }else{ 151 | dest.writeInt(data.size()); 152 | for(String key : data.keySet()){ 153 | dest.writeString(key); 154 | dest.writeString(data.get(key)); 155 | } 156 | } 157 | } 158 | 159 | public static final Parcelable.Creator CREATOR = new Parcelable.Creator() { 160 | public InterceptEvent createFromParcel(Parcel in) { 161 | return new InterceptEvent(in); 162 | } 163 | 164 | public InterceptEvent[] newArray(int size) { 165 | return new InterceptEvent[size]; 166 | } 167 | }; 168 | 169 | 170 | 171 | public InterceptEvent(String hookerName, int intrusiveLevel, 172 | int instanceID, String packageName, String className, 173 | String methodName) { 174 | this(buildRandomUUID(), 0l, 0, hookerName, intrusiveLevel, instanceID, packageName, 175 | className, methodName, null, null, null); 176 | } 177 | 178 | 179 | 180 | public InterceptEvent(UUID idEvent, long timestamp, long relativeTimestamp, String hookerName, int intrusiveLevel, 181 | int instanceId, String packageName, 182 | String className, String methodName, List> parameters, 183 | Entry returns, Map data){ 184 | super(); 185 | this.idEvent = idEvent; 186 | if (timestamp == 0) { 187 | try { 188 | timestamp = Calendar.getInstance().getTime().getTime(); 189 | }catch(Exception e) { 190 | timestamp = 0; 191 | // SubstrateMain.log("Error while computing the current timestamp...", e); 192 | } 193 | } 194 | this.timestamp = timestamp; 195 | this.relativeTimestamp = relativeTimestamp; 196 | this.hookerName = hookerName; 197 | this.intrusiveLevel = intrusiveLevel; 198 | this.instanceID = instanceId; 199 | this.packageName = packageName; 200 | this.className = className; 201 | this.methodName = methodName; 202 | this.parameters = parameters; 203 | this.returns = returns; 204 | this.data = data; 205 | } 206 | 207 | private static UUID buildRandomUUID() { 208 | try { 209 | return UUID.randomUUID(); 210 | } catch (Exception e) { 211 | return UUID.fromString("00000000-1111-2222-3333-444444444444"); 212 | } 213 | } 214 | 215 | public void addParameter(String type, String value) { 216 | if (this.parameters == null) { 217 | this.parameters = new ArrayList>(); 218 | } 219 | this.parameters.add(new AbstractMap.SimpleEntry(type, value)); 220 | } 221 | 222 | public UUID getIdEvent() { 223 | return idEvent; 224 | } 225 | 226 | public void setIdEvent(UUID idEvent) { 227 | this.idEvent = idEvent; 228 | } 229 | 230 | public String getIDXP() { 231 | return IDXP; 232 | } 233 | 234 | public void setIDXP(String iDXP) { 235 | IDXP = iDXP; 236 | } 237 | 238 | public long getTimestamp() { 239 | return timestamp; 240 | } 241 | 242 | public void setTimestamp(long timestamp) { 243 | this.timestamp = timestamp; 244 | } 245 | 246 | public long getRelativeTimestamp() { 247 | return relativeTimestamp; 248 | } 249 | 250 | public void setRelativeTimestamp(long relativeTimestamp) { 251 | this.relativeTimestamp = relativeTimestamp; 252 | } 253 | 254 | public String getHookerName() { 255 | return hookerName; 256 | } 257 | 258 | public void setHookerName(String hookerName) { 259 | this.hookerName = hookerName; 260 | } 261 | 262 | public int getIntrusiveLevel() { 263 | return intrusiveLevel; 264 | } 265 | 266 | public void setIntrusiveLevel(int intrusiveLevel) { 267 | this.intrusiveLevel = intrusiveLevel; 268 | } 269 | 270 | public int getInstanceID() { 271 | return instanceID; 272 | } 273 | 274 | public void setInstanceID(int instanceID) { 275 | this.instanceID = instanceID; 276 | } 277 | 278 | public String getPackageName() { 279 | return packageName; 280 | } 281 | 282 | public void setPackageName(String packageName) { 283 | this.packageName = packageName; 284 | } 285 | 286 | public String getClassName() { 287 | return className; 288 | } 289 | 290 | public void setClassName(String className) { 291 | this.className = className; 292 | } 293 | 294 | public String getMethodName() { 295 | return methodName; 296 | } 297 | 298 | public void setMethodName(String methodName) { 299 | this.methodName = methodName; 300 | } 301 | 302 | public List> getParameters() { 303 | return parameters; 304 | } 305 | 306 | public void setParameters(List> parameters) { 307 | this.parameters = parameters; 308 | } 309 | 310 | public Entry getReturns() { 311 | return returns; 312 | } 313 | 314 | public void setReturns(Entry returns) { 315 | this.returns = returns; 316 | } 317 | 318 | public void setReturns(String type, String value) { 319 | this.returns = new AbstractMap.SimpleEntry(type, value); 320 | 321 | } 322 | 323 | public Map getData() { 324 | return data; 325 | } 326 | 327 | public void setData(Map data) { 328 | this.data = data; 329 | } 330 | 331 | @Override 332 | public String toString() { 333 | StringBuilder builder = new StringBuilder(); 334 | builder.append("InterceptEvent [idEvent="); 335 | builder.append(idEvent); 336 | builder.append(", IDXP="); 337 | builder.append(this.IDXP); 338 | builder.append(", timestamp="); 339 | builder.append(timestamp); 340 | builder.append(", hookerName="); 341 | builder.append(hookerName); 342 | builder.append(", intrusiveLevel="); 343 | builder.append(intrusiveLevel); 344 | builder.append(", instanceID="); 345 | builder.append(instanceID); 346 | builder.append(", packageName="); 347 | builder.append(packageName); 348 | builder.append(", className="); 349 | builder.append(className); 350 | builder.append(", methodName="); 351 | builder.append(methodName); 352 | builder.append("]"); 353 | return builder.toString(); 354 | } 355 | 356 | public String toJson() { 357 | JSONObject object = new JSONObject(); 358 | 359 | try { 360 | // object.put("IdEvent", this.getIdEvent().toString()); 361 | 362 | object.put("Timestamp", this.getTimestamp()); 363 | object.put("RelativeTimestamp", this.getRelativeTimestamp()); 364 | object.put("HookerName", this.getHookerName()); 365 | object.put("IntrusiveLevel", this.getIntrusiveLevel()); 366 | object.put("InstanceID", this.getInstanceID()); 367 | object.put("PackageName", this.getPackageName()); 368 | 369 | object.put("ClassName", this.getClassName()); 370 | object.put("MethodName", this.getMethodName()); 371 | 372 | JSONArray parameters = new JSONArray(); 373 | if (this.getParameters() != null) { 374 | for (Entry parameter : this.getParameters()) { 375 | JSONObject jsonParameter = new JSONObject(); 376 | jsonParameter.put("ParameterType", parameter.getKey()); 377 | jsonParameter.put("ParameterValue", parameter.getValue()); 378 | parameters.put(jsonParameter); 379 | } 380 | } 381 | object.put("Parameters", parameters); 382 | 383 | JSONObject returns = new JSONObject(); 384 | if (this.getReturns() != null) { 385 | returns.put("ReturnType", this.getReturns().getKey()); 386 | returns.put("ReturnValue", this.getReturns().getValue()); 387 | } 388 | object.put("Return", returns); 389 | 390 | 391 | JSONArray data = new JSONArray(); 392 | if (this.getData() != null) { 393 | for (String dataName : this.getData().keySet()) { 394 | if (dataName != null && this.getData().get(dataName) != null) { 395 | JSONObject dataP = new JSONObject(); 396 | dataP.put("DataName", dataName); 397 | dataP.put("DataValue", this.getData().get(dataName)); 398 | } 399 | } 400 | } 401 | object.put("Data", data); 402 | } catch (JSONException e) { 403 | // TODO Auto-generated catch block 404 | e.printStackTrace(); 405 | } 406 | return object.toString(); 407 | } 408 | 409 | } 410 | -------------------------------------------------------------------------------- /src/com/shuwoom/apihooker/hookers/Hooker.java: -------------------------------------------------------------------------------- 1 | package com.shuwoom.apihooker.hookers; 2 | 3 | import java.lang.reflect.Array; 4 | import java.lang.reflect.GenericDeclaration; 5 | import java.lang.reflect.Method; 6 | import java.util.Calendar; 7 | import java.util.HashMap; 8 | import java.util.Iterator; 9 | import java.util.Map; 10 | 11 | import android.content.ComponentName; 12 | import android.content.Context; 13 | import android.content.Intent; 14 | import android.content.ServiceConnection; 15 | import android.os.Bundle; 16 | import android.os.Handler; 17 | import android.os.IBinder; 18 | import android.os.Message; 19 | import android.os.Messenger; 20 | import android.os.RemoteException; 21 | import android.util.Log; 22 | 23 | import com.saurik.substrate.MS; 24 | import com.saurik.substrate.MS.MethodPointer; 25 | import com.shuwoom.apihooker.ApplicationConfig; 26 | import com.shuwoom.apihooker.common.Config; 27 | import com.shuwoom.apihooker.common.InterceptEvent; 28 | import com.shuwoom.apihooker.hookers.interfaces.HookerListener; 29 | 30 | public abstract class Hooker { 31 | 32 | private String hookerName = ""; 33 | private String packageName; 34 | private final long startTimestamp = Calendar.getInstance().getTime() 35 | .getTime(); 36 | private Handler handler; 37 | 38 | private static final int MSG_EVENT = 0x01; 39 | private Messenger mService = null; 40 | boolean isConn = false; 41 | 42 | public Hooker(String hookerName) { 43 | this.hookerName = hookerName; 44 | } 45 | 46 | private ServiceConnection conn = new ServiceConnection() { 47 | 48 | @Override 49 | public void onServiceConnected(ComponentName name, IBinder service) { 50 | mService = new Messenger(service); 51 | isConn = true; 52 | try { 53 | Message msg = Message.obtain(null, 3); 54 | msg.arg1 = 999; 55 | mService.send(msg); 56 | } catch (RemoteException e) { 57 | Log.v(Config.DEBUG_CONNECT_TAG, e.toString()); 58 | e.printStackTrace(); 59 | } 60 | Log.v(Config.DEBUG_CONNECT_TAG, "conncted!!!!!!!!!!!"); 61 | } 62 | 63 | @Override 64 | public void onServiceDisconnected(ComponentName name) { 65 | mService = null; 66 | isConn = false; 67 | Log.v(Config.DEBUG_CONNECT_TAG, "disconncted!!!!!!!!!!!"); 68 | } 69 | 70 | }; 71 | 72 | public abstract void hook(); 73 | 74 | // private HookerListener hookListener = new HookerListener() { 75 | // 76 | // @Override 77 | // public void before(String className, GenericDeclaration method, 78 | // Object resources, InterceptEvent event) { 79 | // Log.v(Config.DEBUG_TAG, 80 | // new StringBuilder("before:{'method':'").append(className) 81 | // .append(".").append(((Method) method).getName()) 82 | // .append("'}").toString()); 83 | // } 84 | // 85 | // @Override 86 | // public void after(String className, GenericDeclaration method, 87 | // Object resources, InterceptEvent event) { 88 | // Log.v(Config.DEBUG_TAG, 89 | // new StringBuilder("after:{'method':'").append(className) 90 | // .append(".").append(((Method) method).getName()) 91 | // .append("'}").toString()); 92 | // 93 | // } 94 | // 95 | // }; 96 | 97 | protected void hookMethods(final HookerListener listener, 98 | final String className, final Map methodsToHook) { 99 | 100 | MS.hookClassLoad(className, new MS.ClassLoadHook() { 101 | 102 | @SuppressWarnings({ "rawtypes", "unchecked" }) 103 | @Override 104 | public void classLoaded(final Class classToHook) { 105 | Map allMethods = new HashMap(); 106 | try { 107 | Class clz = Class.forName(className); 108 | ApplicationConfig.setPackageName(new StringBuilder(clz.getPackage().getName()) 109 | .append(".").append(clz.getSimpleName()).toString()); 110 | for (Method method : clz.getMethods()) { 111 | allMethods.put(method, method.getName()); 112 | } 113 | } catch (ClassNotFoundException e1) { 114 | e1.printStackTrace(); 115 | } 116 | 117 | Iterator iterator = allMethods.entrySet().iterator(); 118 | while (iterator.hasNext()) { 119 | Map.Entry entry = (Map.Entry) iterator.next(); 120 | final Method method = (Method) entry.getKey(); 121 | final String methodName = (String) entry.getValue(); 122 | 123 | if (!methodsToHook.containsKey(methodName)) 124 | continue; 125 | 126 | Log.v(Config.DEBUG_TAG, new StringBuilder("start to hook ") 127 | .append(className).append(".").append(methodName) 128 | .toString()); 129 | 130 | final int intrusiveLevel = methodsToHook.get(methodName); 131 | 132 | final MS.MethodPointer old = new MethodPointer(); 133 | MS.hookMethod(classToHook, method, new MS.MethodHook() { 134 | 135 | @Override 136 | public Object invoked(Object resources, Object... args) 137 | throws Throwable { 138 | 139 | InterceptEvent event = new InterceptEvent( 140 | hookerName, intrusiveLevel, System 141 | .identityHashCode(resources), 142 | "unknown", className, methodName); 143 | 144 | if (args != null) { 145 | for (Object arg : args) { 146 | if (arg != null) { 147 | StringBuilder argValue = new StringBuilder(); 148 | if (arg.getClass().isArray() 149 | && !arg.getClass().getName() 150 | .equals("[B")) { 151 | argValue.append("["); 152 | int len = Array.getLength(arg); 153 | for (int i = 0; i < len - 1; i++) { 154 | argValue.append( 155 | Array.get(arg, i)) 156 | .append(","); 157 | } 158 | argValue.append(Array.get(arg, 159 | len - 1)); 160 | argValue.append("]"); 161 | } else { 162 | argValue.append(arg.toString()); 163 | } 164 | 165 | event.addParameter(arg.getClass() 166 | .getName(), argValue.toString()); 167 | } else { 168 | event.addParameter(null, null); 169 | } 170 | } 171 | } 172 | 173 | if (ApplicationConfig.getPackageName() != null) { 174 | event.setPackageName(ApplicationConfig 175 | .getPackageName()); 176 | } 177 | 178 | final Context appContext = ApplicationConfig 179 | .getContext(); 180 | if (appContext != null) { 181 | doBindService(appContext); 182 | Log.v(Config.DEBUG_TAG, 183 | new StringBuilder("hook context from****************>") 184 | .append(appContext.getPackageName()).toString()); 185 | } 186 | 187 | if (listener != null) { 188 | listener.before(className, method, resources, 189 | event); 190 | } 191 | 192 | Object result = old.invoke(resources, args); 193 | 194 | if (result != null) { 195 | event.setReturns(result.getClass().getName(), 196 | result.toString()); 197 | } else { 198 | event.setReturns(null, null); 199 | } 200 | Log.v(Config.DEBUG_TAG, event.toJson()); 201 | insertEvent(event); 202 | 203 | if (listener != null) { 204 | listener.after(className, method, resources, 205 | event); 206 | } 207 | 208 | return result; 209 | } 210 | 211 | }, old); 212 | } 213 | } 214 | }); 215 | } 216 | 217 | private void doBindService(Context appContext) { 218 | Intent intent = new Intent(); 219 | intent.setAction("com.shuwoom.aidl.hooker"); 220 | appContext.bindService(intent, conn, Context.BIND_AUTO_CREATE); 221 | } 222 | 223 | private void insertEvent(InterceptEvent event) { 224 | long relativeTimestamp = event.getTimestamp() - this.startTimestamp; 225 | event.setRelativeTimestamp(relativeTimestamp); 226 | 227 | if (isConn) { 228 | try { 229 | Message msg = Message.obtain(null, MSG_EVENT); 230 | msg.replyTo = mService; 231 | Bundle eventToSend = new Bundle(); 232 | 233 | eventToSend.putParcelable("eventKey", event); 234 | msg.setData(eventToSend); 235 | mService.send(msg); 236 | } catch (RemoteException e) { 237 | Log.v(Config.DEBUG_TAG, e.toString()); 238 | } 239 | } 240 | } 241 | } 242 | -------------------------------------------------------------------------------- /src/com/shuwoom/apihooker/hookers/NetworkHooker.java: -------------------------------------------------------------------------------- 1 | package com.shuwoom.apihooker.hookers; 2 | 3 | import java.util.HashMap; 4 | import java.util.Map; 5 | 6 | import android.util.Log; 7 | 8 | import com.shuwoom.apihooker.common.Config; 9 | 10 | public class NetworkHooker extends Hooker { 11 | 12 | public static final String NAME = "Network"; 13 | 14 | public NetworkHooker() { 15 | super(NetworkHooker.NAME); 16 | } 17 | 18 | @Override 19 | public void hook() { 20 | hookIOBridgeClass(); 21 | attachOnAbstractHttpClientClass(); 22 | attachOnHttpGetClass(); 23 | attachOnUrlClass(); 24 | attachOnIOExceptionClass(); 25 | attachOnSocketClass(); 26 | attachOnProxyClass(); 27 | attachOnServerSocketClass(); 28 | attachOnSSLCertificateSocketFactoryClass(); 29 | attachOnSSLParametersClass(); 30 | attachOnSSLContextClass(); 31 | attachOnHttpURLConnection(); 32 | attachOnHttpsURLConnection(); 33 | attachOnWebviewClass(); 34 | attachOnWebSettingsClass(); 35 | } 36 | 37 | private void hookIOBridgeClass() { 38 | String className = "libcore.io.IoBridge"; 39 | Map methodsToHook = new HashMap(); 40 | 41 | // methodsToHook.put("open", 1); This is in common with filesystem 42 | // operation. 43 | methodsToHook.put("recvfrom", 1); 44 | // methodsToHook.put("read", 1); 45 | 46 | // methodsToHook.put("write", 2); 47 | methodsToHook.put("sendto", 2); 48 | 49 | methodsToHook.put("getSocketLocalAddress", 1); 50 | methodsToHook.put("getSocketLocalPort", 1); 51 | 52 | methodsToHook.put("closeSocket", 1); 53 | methodsToHook.put("connectErrno", 1); 54 | methodsToHook.put("connect", 2); 55 | methodsToHook.put("bind", 1); 56 | 57 | try { 58 | hookMethods(null, className, methodsToHook); 59 | } catch (Exception e) { 60 | StringBuilder sb = new StringBuilder(className); 61 | sb.append("=>").append(e.toString()); 62 | Log.v(Config.DEBUG_ERROR, sb.toString()); 63 | } 64 | } 65 | 66 | private void attachOnAbstractHttpClientClass() { 67 | String className = "org.apache.http.impl.client.AbstractHttpClient"; 68 | Map methodsToHook = new HashMap(); 69 | 70 | methodsToHook.put("execute", 2); 71 | methodsToHook.put("getAuthSchemes", 1); 72 | methodsToHook.put("getCookiesStore", 1); 73 | methodsToHook.put("getCredentialProvider", 1); 74 | methodsToHook.put("getParams", 1); 75 | methodsToHook.put("setParams", 2); 76 | 77 | try { 78 | hookMethods(null, className, methodsToHook); 79 | } catch (Exception e) { 80 | StringBuilder sb = new StringBuilder(className); 81 | sb.append("=>").append(e.toString()); 82 | Log.v(Config.DEBUG_ERROR, sb.toString()); 83 | } 84 | 85 | } 86 | 87 | private void attachOnHttpGetClass() { 88 | String className = "org.apache.http.client.methods.HttpGet"; 89 | Map methodsToHook = new HashMap(); 90 | 91 | methodsToHook.put("HttpGet", 2); 92 | methodsToHook.put("getMethod", 1); 93 | methodsToHook.put("getURI", 1); 94 | 95 | try { 96 | hookMethods(null, className, methodsToHook); 97 | } catch (Exception e) { 98 | StringBuilder sb = new StringBuilder(className); 99 | sb.append("=>").append(e.toString()); 100 | Log.v(Config.DEBUG_ERROR, sb.toString()); 101 | } 102 | 103 | } 104 | 105 | private void attachOnUrlClass() { 106 | String className = "java.net.URL"; 107 | Map methodsToHook = new HashMap(); 108 | 109 | methodsToHook.put("URL", 0); 110 | methodsToHook.put("getAuthority", 0); 111 | methodsToHook.put("getContent", 0); 112 | methodsToHook.put("getDefaultPort", 0); 113 | methodsToHook.put("getFile", 0); 114 | methodsToHook.put("getHost", 0); 115 | methodsToHook.put("getPath", 0); 116 | methodsToHook.put("getPort", 0); 117 | methodsToHook.put("getProtocol", 0); 118 | methodsToHook.put("getQuery", 0); 119 | methodsToHook.put("openConnection", 1); 120 | methodsToHook.put("openStream", 1); 121 | methodsToHook.put("toURI", 0); 122 | 123 | hookMethods(null, className, methodsToHook); 124 | } 125 | 126 | private void attachOnIOExceptionClass() { 127 | String className = "java.io.IOException"; 128 | Map methodsToHook = new HashMap(); 129 | 130 | methodsToHook.put("IOException", 0); 131 | 132 | try { 133 | hookMethods(null, className, methodsToHook); 134 | } catch (Exception e) { 135 | StringBuilder sb = new StringBuilder(className); 136 | sb.append("=>").append(e.toString()); 137 | Log.v(Config.DEBUG_ERROR, sb.toString()); 138 | } 139 | } 140 | 141 | private void attachOnSocketClass() { 142 | String className = "java.net.Socket"; 143 | Map methodsToHook = new HashMap(); 144 | 145 | methodsToHook.put("Socket", 2); 146 | methodsToHook.put("bind", 2); 147 | methodsToHook.put("close", 1); 148 | methodsToHook.put("connect", 2); 149 | methodsToHook.put("getInetAddress", 1); 150 | methodsToHook.put("getInputStream", 1); 151 | methodsToHook.put("getLocalAddress", 1); 152 | methodsToHook.put("getLocalPort", 1); 153 | methodsToHook.put("getLocalSocketAddress", 1); 154 | methodsToHook.put("getOutputStream", 1); 155 | methodsToHook.put("getPort", 1); 156 | methodsToHook.put("sendUrgentData", 2); 157 | methodsToHook.put("getPort", 1); 158 | methodsToHook.put("setReuseAddress", 1); 159 | methodsToHook.put("setSocketImplFactory", 1); 160 | methodsToHook.put("setTcpNoDelay", 1); 161 | methodsToHook.put("shutdownInput", 1); 162 | methodsToHook.put("shutdownOutput", 1); 163 | 164 | try { 165 | hookMethods(null, className, methodsToHook); 166 | } catch (Exception e) { 167 | StringBuilder sb = new StringBuilder(className); 168 | sb.append("=>").append(e.toString()); 169 | Log.v(Config.DEBUG_ERROR, sb.toString()); 170 | } 171 | 172 | } 173 | 174 | private void attachOnProxyClass() { 175 | String className = "java.net.Proxy"; 176 | Map methodsToHook = new HashMap(); 177 | 178 | methodsToHook.put("Proxy", 0); 179 | 180 | try { 181 | hookMethods(null, className, methodsToHook); 182 | } catch (Exception e) { 183 | StringBuilder sb = new StringBuilder(className); 184 | sb.append("=>").append(e.toString()); 185 | Log.v(Config.DEBUG_ERROR, sb.toString()); 186 | } 187 | 188 | } 189 | 190 | private void attachOnServerSocketClass() { 191 | String className = "java.net.ServerSocket"; 192 | Map methodsToHook = new HashMap(); 193 | 194 | methodsToHook.put("ServerSocket", 0); 195 | methodsToHook.put("accept", 0); 196 | methodsToHook.put("bind", 0); 197 | 198 | try { 199 | hookMethods(null, className, methodsToHook); 200 | } catch (Exception e) { 201 | StringBuilder sb = new StringBuilder(className); 202 | sb.append("=>").append(e.toString()); 203 | Log.v(Config.DEBUG_ERROR, sb.toString()); 204 | } 205 | 206 | } 207 | 208 | private void attachOnSSLCertificateSocketFactoryClass() { 209 | String className = "android.net.SSLCertificateSocketFactory"; 210 | Map methodsToHook = new HashMap(); 211 | 212 | methodsToHook.put("SSLCertificateSocketFactory", 0); 213 | methodsToHook.put("getDefault", 0); 214 | methodsToHook.put("createSocket", 0); 215 | methodsToHook.put("getHttpSocketFactory", 0); 216 | methodsToHook.put("getNpnSelectedProtocol", 0); 217 | methodsToHook.put("setHostname", 0); 218 | methodsToHook.put("setKeyManager", 0); 219 | methodsToHook.put("setNpnProtocols", 0); 220 | methodsToHook.put("setTrustManagers", 0); 221 | methodsToHook.put("setUseSessionTickets", 0); 222 | 223 | try { 224 | hookMethods(null, className, methodsToHook); 225 | } catch (Exception e) { 226 | StringBuilder sb = new StringBuilder(className); 227 | sb.append("=>").append(e.toString()); 228 | Log.v(Config.DEBUG_ERROR, sb.toString()); 229 | } 230 | 231 | } 232 | 233 | private void attachOnSSLParametersClass() { 234 | String className = "javax.net.ssl.SSLParameters"; 235 | Map methodsToHook = new HashMap(); 236 | 237 | methodsToHook.put("SSLParameters", 0); 238 | methodsToHook.put("setCipherSuites", 0); 239 | methodsToHook.put("setNeedClientAuth", 0); 240 | methodsToHook.put("setProtocols", 0); 241 | methodsToHook.put("setWantClientAuth", 0); 242 | 243 | try { 244 | hookMethods(null, className, methodsToHook); 245 | } catch (Exception e) { 246 | StringBuilder sb = new StringBuilder(className); 247 | sb.append("=>").append(e.toString()); 248 | Log.v(Config.DEBUG_ERROR, sb.toString()); 249 | } 250 | 251 | } 252 | 253 | private void attachOnSSLContextClass() { 254 | String className = "javax.net.ssl.SSLContext"; 255 | Map methodsToHook = new HashMap(); 256 | 257 | methodsToHook.put("getInstance", 0); 258 | methodsToHook.put("init", 0); 259 | methodsToHook.put("createSSLEngine", 0); 260 | methodsToHook.put("getDefault", 0); 261 | 262 | try { 263 | hookMethods(null, className, methodsToHook); 264 | } catch (Exception e) { 265 | StringBuilder sb = new StringBuilder(className); 266 | sb.append("=>").append(e.toString()); 267 | Log.v(Config.DEBUG_ERROR, sb.toString()); 268 | } 269 | 270 | } 271 | 272 | private void attachOnHttpURLConnection() { 273 | String className = "java.net.HttpURLConnection"; 274 | Map methodsToHook = new HashMap(); 275 | 276 | methodsToHook.put("HttpURLConnection", 0); 277 | methodsToHook.put("getErrorStream", 0); 278 | methodsToHook.put("getFollowRedirects", 0); 279 | methodsToHook.put("getHeaderFieldDate", 0); 280 | methodsToHook.put("getInstanceFollowRedirects", 0); 281 | methodsToHook.put("getPermission", 0); 282 | methodsToHook.put("setChunkedStreamingMode", 0); 283 | methodsToHook.put("setFixedLengthStreamingMode", 0); 284 | methodsToHook.put("setFollowRedirects", 0); 285 | methodsToHook.put("setInstanceFollowRedirects", 0); 286 | methodsToHook.put("setRequestMethod", 0); 287 | methodsToHook.put("setDoOutput", 0); 288 | 289 | try { 290 | hookMethods(null, className, methodsToHook); 291 | } catch (Exception e) { 292 | StringBuilder sb = new StringBuilder(className); 293 | sb.append("=>").append(e.toString()); 294 | Log.v(Config.DEBUG_ERROR, sb.toString()); 295 | } 296 | 297 | } 298 | 299 | private void attachOnHttpsURLConnection() { 300 | final String className = "javax.net.ssl.HttpsURLConnection"; 301 | 302 | Map methodsToHook = new HashMap(); 303 | 304 | methodsToHook.put("getDefaultHostnameVerifier", 0); 305 | methodsToHook.put("getDefaultSSLSocketFactory", 0); 306 | methodsToHook.put("getHostnameVerifier", 0); 307 | methodsToHook.put("getLocalPrincipal", 0); 308 | methodsToHook.put("getSSLSocketFactory", 0); 309 | methodsToHook.put("setDefaultHostnameVerifier", 0); 310 | methodsToHook.put("setDefaultSSLSocketFactory", 0); 311 | methodsToHook.put("setHostnameVerifier", 0); 312 | methodsToHook.put("setSSLSocketFactory", 0); 313 | 314 | try { 315 | hookMethods(null, className, methodsToHook); 316 | } catch (Exception e) { 317 | StringBuilder sb = new StringBuilder(className); 318 | sb.append("=>").append(e.toString()); 319 | Log.v(Config.DEBUG_ERROR, sb.toString()); 320 | } 321 | } 322 | 323 | private void attachOnWebviewClass() { 324 | String className = "android.webkit.WebView"; 325 | Map methodsToHook = new HashMap(); 326 | 327 | methodsToHook.put("addJavascriptInterface", 2); 328 | methodsToHook.put("capturePicture", 2); 329 | methodsToHook.put("clearSslPreferences", 1); 330 | methodsToHook.put("evaluateJavascript", 2); 331 | methodsToHook.put("findAddress", 0); 332 | methodsToHook.put("getCertificate", 0); 333 | methodsToHook.put("getSettings", 0); 334 | 335 | methodsToHook.put("isPrivateBrowsingEnabled", 0); 336 | methodsToHook.put("loadData", 2); 337 | methodsToHook.put("loadDataWithBaseURL", 2); 338 | methodsToHook.put("loadUrl", 2); 339 | methodsToHook.put("postUrl", 0); 340 | methodsToHook.put("removeJavascriptInterface", 2); 341 | methodsToHook.put("restoreState", 1); 342 | methodsToHook.put("savePassword", 1); 343 | methodsToHook.put("saveState", 1); 344 | methodsToHook.put("setCertificate", 2); 345 | methodsToHook.put("setHttpAuthUsernamePassword", 2); 346 | methodsToHook.put("setWebContentsDebuggingEnabled", 2); 347 | 348 | try { 349 | hookMethods(null, className, methodsToHook); 350 | } catch (Exception e) { 351 | StringBuilder sb = new StringBuilder(className); 352 | sb.append("=>").append(e.toString()); 353 | Log.v(Config.DEBUG_ERROR, sb.toString()); 354 | } 355 | } 356 | 357 | private void attachOnWebSettingsClass() { 358 | String className = "android.webkit.WebSettings"; 359 | Map methodsToHook = new HashMap(); 360 | 361 | methodsToHook.put("setAllowContentAccess", 2); 362 | methodsToHook.put("setAllowFileAccess", 2); 363 | methodsToHook.put("setDatabaseEnabled", 2); 364 | methodsToHook.put("setDatabasePath", 2); 365 | methodsToHook.put("setJavaScriptEnabled", 2); 366 | methodsToHook.put("setSavePassword", 2); 367 | 368 | try { 369 | hookMethods(null, className, methodsToHook); 370 | } catch (Exception e) { 371 | StringBuilder sb = new StringBuilder(className); 372 | sb.append("=>").append(e.toString()); 373 | Log.v(Config.DEBUG_ERROR, sb.toString()); 374 | } 375 | } 376 | } 377 | -------------------------------------------------------------------------------- /src/com/shuwoom/apihooker/hookers/interfaces/HookerListener.java: -------------------------------------------------------------------------------- 1 | package com.shuwoom.apihooker.hookers.interfaces; 2 | 3 | import java.lang.reflect.GenericDeclaration; 4 | 5 | import com.shuwoom.apihooker.common.InterceptEvent; 6 | 7 | public interface HookerListener { 8 | 9 | public void before(String className, GenericDeclaration method, Object resources, InterceptEvent event); 10 | 11 | public void after(String className, GenericDeclaration method, Object resources, InterceptEvent event); 12 | } 13 | -------------------------------------------------------------------------------- /src/com/shuwoom/apihooker/services/ReceiverService.java: -------------------------------------------------------------------------------- 1 | package com.shuwoom.apihooker.services; 2 | 3 | import android.app.Service; 4 | import android.content.Intent; 5 | import android.os.Handler; 6 | import android.os.IBinder; 7 | import android.os.Message; 8 | import android.os.Messenger; 9 | import android.util.Log; 10 | 11 | import com.shuwoom.apihooker.common.Config; 12 | import com.shuwoom.apihooker.common.DataChanger; 13 | import com.shuwoom.apihooker.common.InterceptEvent; 14 | 15 | public class ReceiverService extends Service{ 16 | 17 | private static final int MSG_EVENT = 0x01; 18 | 19 | private Messenger messenger = new Messenger(new Handler(){ 20 | 21 | @Override 22 | public void handleMessage(Message msgFromClient) { 23 | switch(msgFromClient.what){ 24 | case MSG_EVENT: 25 | msgFromClient.getData().setClassLoader(InterceptEvent.class.getClassLoader()); 26 | InterceptEvent event = (InterceptEvent)msgFromClient.getData().getParcelable("eventKey"); 27 | if(event != null){ 28 | if(event.getPackageName().equals("com.kugou.android")){ 29 | Log.v(Config.DEBUG_CONNECT_TAG, "receive event msg from client=>" + event.toJson()); 30 | // DataChanger.getInstance(getApplication()).update(event); 31 | } 32 | } 33 | break; 34 | case 3: 35 | Log.v(Config.DEBUG_CONNECT_TAG, "receive connect msg from client"); 36 | break; 37 | } 38 | super.handleMessage(msgFromClient); 39 | } 40 | }); 41 | 42 | @Override 43 | public IBinder onBind(Intent intent) { 44 | return messenger.getBinder(); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /test_pic/activity_show.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/guanchao/AndroidAPIHooker/3cf38b2e3ca49e75831067675beb4b740e316b00/test_pic/activity_show.png -------------------------------------------------------------------------------- /test_pic/logcat.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/guanchao/AndroidAPIHooker/3cf38b2e3ca49e75831067675beb4b740e316b00/test_pic/logcat.png --------------------------------------------------------------------------------