djwdj 发表于 2017-12-28 18:28

android 启动AndroidManifest.xml未注册的class 不占坑版

@Override
    protected void attachBaseContext(Context newBase) {
      super.attachBaseContext(newBase);

      try {
            /**
             * 欺骗ActivityManagerNative,启动AndroidManifest.xml未注册的class
             */
            Class<?> activityManagerNativeClass = Class.forName("android.app" +
                ".ActivityManagerNative");

            Field gDefaultField = activityManagerNativeClass.getDeclaredField("gDefault");
            gDefaultField.setAccessible(true);

            Object gDefault = gDefaultField.get(null);

            // gDefault是一个 android.util.Singleton对象; 我们取出这个单例里面的字段
            Class<?> singleton = Class.forName("android.util.Singleton");
            Field mInstanceField = singleton.getDeclaredField("mInstance");
            mInstanceField.setAccessible(true);

            // ActivityManagerNative 的gDefault对象里面原始的 IActivityManager对象
            final Object rawIActivityManager = mInstanceField.get(gDefault);

            // 创建一个这个对象的代{过}{滤}理对象, 然后替换这个字段, 让我们的代{过}{滤}理对象帮忙干活
            Class<?> iActivityManagerInterface = Class.forName("android.app.IActivityManager");
            Object proxy = Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(),
    new Class<?>[] {iActivityManagerInterface}, new InvocationHandler() {


   @Override
   public Object invoke(Object proxy, Method method, Object[] args) throws
   Throwable {
      if ("startActivity".equals(method.getName())) {
       Intent raw;
       int index = 0;

       for (int i = 0; i < args.length; i++) {
      if (args instanceof Intent) {
         index = i;
         break;
      }
       }
       raw = (Intent) args;

       Intent newIntent = new Intent();

       // 这替身ComponentName是调用本身class,可按需更换
       newIntent.setComponent(new ComponentName(getPackageName(),getPackageName()+"."+getLocalClassName()));

       // 把我们原始要启动的TargetActivity先存起来
       newIntent.putExtra("_", raw);

       // 替换掉Intent, 达到欺骗AMS的目的
       args = newIntent;

       return method.invoke(rawIActivityManager, args);
      }
      return method.invoke(rawIActivityManager, args);
   }
    });
            mInstanceField.set(gDefault, proxy);


            /**
             * 欺骗ActivityThread
             */

            // 先获取到当前的ActivityThread对象
            Class<?> activityThreadClass = Class.forName("android.app.ActivityThread");
            Field currentActivityThreadField = activityThreadClass.getDeclaredField
   ("sCurrentActivityThread");
            currentActivityThreadField.setAccessible(true);
            Object currentActivityThread = currentActivityThreadField.get(null);

            // 由于ActivityThread一个进程只有一个,我们获取这个对象的mH
            Field mHField = activityThreadClass.getDeclaredField("mH");
            mHField.setAccessible(true);
            final Handler mH = (Handler) mHField.get(currentActivityThread);

            Field mCallBackField = Handler.class.getDeclaredField("mCallback");
            mCallBackField.setAccessible(true);

            mCallBackField.set(mH, new Handler.Callback() {
   @Override
   public boolean handleMessage(Message msg) {
      if (msg.what == 100) {
       Object obj = msg.obj;
       try {
      // 把替身恢复成真身
      Field intent = obj.getClass().getDeclaredField("intent");
      intent.setAccessible(true);
      Intent raw = (Intent) intent.get(obj);

      Intent target = raw.getParcelableExtra("_");
      raw.setComponent(target.getComponent());

       } catch (NoSuchFieldException e) {
      e.printStackTrace();
       } catch (IllegalAccessException e) {
      e.printStackTrace();
       }
       mH.handleMessage(msg);
      }
      return true;
   }
    });

      } catch (Exception e) {
            e.printStackTrace();
      }
    }

蓦留 发表于 2017-12-28 19:05

结合实例更好吧   说下有什么作用
页: [1]
查看完整版本: android 启动AndroidManifest.xml未注册的class 不占坑版