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); } } } });