美文网首页
hook activity的mInstrumentation实现

hook activity的mInstrumentation实现

作者: Lee_5566 | 来源:发表于2020-12-11 10:01 被阅读0次
    image.png

    理论知识参考:activity的启动流程(一)

    hook activity

    下载反射使用代码RefInvoke.java

    hook思路:

    • 获取实例中的mInstrumentation区域
    • 创建MyInstrumentation对象
    • 使用MyInstrumentation对象替换掉实例中的mInstrumentation区域

    核心代码如下:

    // hook实现静态代理
    // hook本MainActivity实例的mInstrumentation
    // 替换为myInstrumentation
    Object mInstrumentation = RefInvoke.getFieldOjbect(Activity.class.getName(), this, "mInstrumentation");
    Instrumentation myInstrumentation = new MyInstrumentation((Instrumentation)mInstrumentation);
    RefInvoke.setFieldOjbect(Activity.class.getName(), "mInstrumentation", this, myInstrumentation);
    

    实战代码

    MainActivity.java:

    package com.exmple.hookactivity;
    
    import androidx.appcompat.app.AppCompatActivity;
    
    import android.app.Activity;
    import android.app.Instrumentation;
    import android.content.Intent;
    import android.os.Bundle;
    import android.view.View;
    import android.widget.Button;
    
    import com.exmple.hookactivity.hook.MyInstrumentation;
    import com.exmple.hookactivity.hook.RefInvoke;
    
    /**
     * @author Lee
     * @date 20/12/10
     */
    public class MainActivity extends AppCompatActivity {
    
        Button button;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
    
            // hook实现静态代理
            // hook本MainActivity实例的mInstrumentation
            // 替换为myInstrumentation
            Object mInstrumentation = RefInvoke.getFieldOjbect(Activity.class.getName(), this, "mInstrumentation");
            Instrumentation myInstrumentation = new MyInstrumentation((Instrumentation)mInstrumentation);
            RefInvoke.setFieldOjbect(Activity.class.getName(), "mInstrumentation", this, myInstrumentation);
    
            button = (Button)findViewById(R.id.button);
            button.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    Intent intent = new Intent();
                    intent.setClass(MainActivity.this, Second.class);
    
                    startActivity(intent);
                }
            });
        }
    }
    

    Second.java:

    package com.exmple.hookactivity;
    
    import androidx.appcompat.app.AppCompatActivity;
    
    import android.os.Bundle;
    
    /**
     * @author Lee
     * @date 20/12/10
     */
    public class Second extends AppCompatActivity {
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_second);
        }
    }
    

    RefInvoke.java:

    package com.exmple.hookactivity.hook;
    
    import java.lang.reflect.Field;
    import java.lang.reflect.Method;
    
    public class RefInvoke {
    
        public static  Object invokeStaticMethod(String class_name, String method_name, Class[] pareTyple, Object[] pareVaules){
    
            try {
                Class<?> obj_class = Class.forName(class_name);
                Method method = obj_class.getMethod(method_name,pareTyple);
                return method.invoke(null, pareVaules);
            } catch (Exception e) {
                e.printStackTrace();
            }
            return null;
    
        }
    
        public static  Object invokeMethod(String class_name, String method_name, Object obj ,Class[] pareTyple, Object[] pareVaules){
    
            try {
                Class<?> obj_class = Class.forName(class_name);
                Method method = obj_class.getMethod(method_name,pareTyple);
                return method.invoke(obj, pareVaules);
            } catch (Exception e) {
                e.printStackTrace();
            }
            return null;
        }
    
        public static Object getFieldOjbect(String class_name,Object obj, String filedName){
            try {
                Class<?> obj_class = Class.forName(class_name);
                Field field = obj_class.getDeclaredField(filedName);
                field.setAccessible(true);
                return field.get(obj);
            } catch (Exception e) {
                e.printStackTrace();
            }
            return null;
        }
    
        public static Object getStaticFieldOjbect(String class_name, String filedName){
    
            try {
                Class<?> obj_class = Class.forName(class_name);
                Field field = obj_class.getDeclaredField(filedName);
                field.setAccessible(true);
                return field.get(null);
            } catch (Exception e) {
                e.printStackTrace();
            }
            return null;
        }
    
        public static void setFieldOjbect(String classname, String filedName, Object obj, Object filedVaule){
            try {
                Class<?> obj_class = Class.forName(classname);
                Field field = obj_class.getDeclaredField(filedName);
                field.setAccessible(true);
                field.set(obj, filedVaule);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    
        public static void setStaticOjbect(String class_name, String filedName, Object filedVaule){
            try {
                Class<?> obj_class = Class.forName(class_name);
                Field field = obj_class.getDeclaredField(filedName);
                field.setAccessible(true);
                field.set(null, filedVaule);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    
    }
    

    MyInstrumentation.java:

    package com.exmple.hookactivity.hook;
    
    import android.app.Activity;
    import android.app.Instrumentation;
    import android.content.Context;
    import android.content.Intent;
    import android.os.Bundle;
    import android.os.IBinder;
    import android.util.Log;
    
    import java.lang.reflect.Method;
    
    /**
     * @author weishu
     * @date 16/1/28
     */
    public class MyInstrumentation extends Instrumentation {
        private static final String TAG = "MyInstrumentation";
    
        // ActivityThread中原始的对象, 保存起来
        Instrumentation mBase;
    
        public MyInstrumentation(Instrumentation base) {
            mBase = base;
        }
    
        public ActivityResult execStartActivity(
                Context who, IBinder contextThread, IBinder token, Activity target,
                Intent intent, int requestCode, Bundle options) {
    
            // Hook之前, XXX到此一游!
            Log.e(TAG, "\n执行了startActivity, 参数如下: \n" + "who = [" + who + "], " +
                    "\ncontextThread = [" + contextThread + "], \ntoken = [" + token + "], " +
                    "\ntarget = [" + target + "], \nintent = [" + intent +
                    "], \nrequestCode = [" + requestCode + "], \noptions = [" + options + "]");
    
            // 开始调用原始的方法, 调不调用随你,但是不调用的话, 所有的startActivity都失效了.
            // 由于这个方法是隐藏的,因此需要使用反射调用;首先找到这个方法
            try {
                Method execStartActivity = Instrumentation.class.getDeclaredMethod(
                        "execStartActivity",
                        Context.class, IBinder.class, IBinder.class, Activity.class,
                        Intent.class, int.class, Bundle.class);
                execStartActivity.setAccessible(true);
                return (ActivityResult) execStartActivity.invoke(mBase, who,
                        contextThread, token, target, intent, requestCode, options);
            } catch (Exception e) {
                // 某该死的rom修改了  需要手动适配
                throw new RuntimeException("do not support!!! pls adapt it");
            }
        }
    }
    
    

    activity_main.xml:

    <?xml version="1.0" encoding="utf-8"?>
    <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:context=".MainActivity">
    
        <Button
            android:id="@+id/button"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Start Second"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent" />
    
    </androidx.constraintlayout.widget.ConstraintLayout>
    

    activity_second.xml:

    <?xml version="1.0" encoding="utf-8"?>
    <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:context=".Second">
    
        <TextView
            android:id="@+id/textView"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Hello Second Activity"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent" />
    </androidx.constraintlayout.widget.ConstraintLayout>
    

    执行效果:


    image.png

    相关文章

      网友评论

          本文标题:hook activity的mInstrumentation实现

          本文链接:https://www.haomeiwen.com/subject/eyhrgktx.html