美文网首页
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