public class Main implements IXposedHookLoadPackage { /* 攔截方法一: 實現hook操作:使用hook類的名稱進行內部查找 hook_method(類型,類加載器,方法名,參數類型和調用 ) 類加載器 作用:將java類加載到java虛擬機 Object... 作用:這是java的varag功能,允許方法擁有一個可變長度的參數列表,起始實際上這個參數就是一個數組 */ private void hook_method(String className,ClassLoader classLoader,String methodName,Object...parameterTypesAndCall){ try{ //找到要攔截的方法並且攔截這個方法 XposedHelpers.findAndHookMethod(className,classLoader,methodName,parameterTypesAndCallback); }catch(Exception e){ XposedBridge.log(e); } } /* 攔截方法二: 實現hook操作:使用反射找到要hook的方法 hook_methods(類名,方法名,回調方法) 回調方法選擇 XC_MethodHook 或 XC_MethodReplacement Class<?>clazz = Class.forName(className); 注意:每次JVM創建一個對象時候,也創建一個java.lang.Class對象來描述該對象的類型。同一個類的所有實例,都共享同一個Class對象。 使用java.lang.Class的靜態方法 forName() 可以用給定的className,即類名來創建一個對象。 可以使用clazz.newInstance()創建一個className表示的類的實例。 這里的Class<?>clazz 表示 clazz 可以是任意類型的Class對象。 java.lang.reflect.Modifier.isPublic(int mod)方法判斷如果給定mod參數包含public修飾符,則返回true,否則返回false java.lang.reflect.Modifier.isAbstract(int mod)方法判定如果整數參數包含abstract修飾符,則返回true,否則返回false java.lang.reflect.Method.getModifiers()方法返回由此Method對象表示的方法的Java語言修飾符轉為的整數值。 Modifier類應用於解碼修飾符。 java.lang.Class.getDeclaredMethods() 方法返回一個Method對象的數組,包括公共,保護,默認(包)訪問和私有方法, 但不包括繼承的方法。該方法返回一個長度為0的數組,如果類或接口不聲明 */ private void hook_methods(String className, String methodName, XC_MethodHook xc_methodHook) { try { Class<?> clazz = Class.forName(className); //反射 for (Method method : clazz.getDeclaredMethods()) //如果 (通過反射找到的方法名和准備hook的方法名相同 && 方法判定如果整數參數包含abstract修飾符,則返回true,否則返回false && // 方法判斷如果給定參數包含public修飾符,則返回true,否則返回false ) if (method.getName().equals(methodName) && !Modifier.isAbstract(method.getModifiers()) && Modifier.isPublic(method.getModifiers())) { XposedBridge.hookMethod(method, xc_methodHook); } } catch (Exception e) { XposedBridge.log(e); } } /* java.lang.Throwable 類是在Java語言中所有錯誤和異常的超類。只有在這個類(或它的一個子類)的實例對象由Java虛擬機拋出,也可以由Java throw語句拋出 對於回調過來的參數MethodHookParam param一般有以下2種用處: 1.param.args[0]:得到被攔截方法的第一個參數,返回值是Object 2.param.getResult():得到被攔截方法的執行結果,返回值是Object */ @Override public void handleLoadPackage(final LoadPackageParam lpp )throws Throwable{ //函數內部只調用了一個方法,就是前面兩個方法中的一個,這里是使用了使用了第一個hook方法,在參數中傳入了一個匿名類 hook_method("android.telephony.TelephonyManager",lpp.classLoader,"getDeviceId",new XC_MethodHook(){ @Override //MethodHookParam 鈎子方法參數 protected void afterHookedMethod(MethodHookParam param) throws Throwable{ /* 具體的邏輯 例如: Object obj = param.getResult(); param.setResult("chen sheng"); */ } }); } } *********************************************************************************************************************************** 上面是hook了系統的imei信息,下面是Hook系統的地理位置信息: 方法1:在初始化的時候調用getLastKnowLocation()方法獲取最后一個系統中的地理位置信息。 方法2:監聽地理位置變化的回調借口中的onLocationChanged()回調方法 LocationListener locationListener = new LocationListener(){ .... .... .... //回調方法 @Override public void onLocationChanged(Location location){ showLocation(location); } } Hook方法一: hook_methods("android.location.LocationManager","getLastKnowLocation",new XC_MethodHook(){ @Override protected void afterHookMethod(MethodHookParam param) throws Throwable{ Location l = new Location(LocationManager.PASSIVE_PROVIEDR); double lo = -10000d; double la = -10000d; l.setLatitude(lo); l.setLongitude(la); param.setResult(l); } }); Hook方法二: 思路: 首先找到添加監聽位置的方法requestLocationUpdates() 然后通過反射得到這個回調對象,然后在進行操作 因為回調方法是通過參數把Location對象傳遞過來,這里需要修改參數 hook_methods("android.location.LocationManager","getLastKnowLocation",new XC_MethodHook(){ @Override protected void afterHookMethod(MethodHookParam param) throws Throwable{ if(param.args.length == 4 && (param.args[0] instanceof String)){ LocationListener ll = (LocationListener)param.args[3]; Class<?> clazz = LocationListener.class; Method m = null; for(Method method: clazz.getDeclaredMethods()){ if(method.getName.equals("onLocationChanged")){ m = method; break; } } try{ if(m != null){ Object[] args = new Object[1]; Location l = new Location(LocationManager.PASSIVE_PROVIDER); double lo = -10000d; double la = -10000d; l.setLatitude(lo); l.setLongitude(la); args[0]=l; m.invoke(ll,args); } }catch(Exception e){ XposedBridge.log(e); } } } });