你想成为Android高级工程师你还得学习Hook

目的

这篇文章是让大家体会hook技术大概是什么样子,在那些地方可以应用到。后面文章将深入hook技术,以及解析市面上现有的hook开源框架原理。

在前面的文章中我们已经说过什么是代理模式,那我们就先使用最简单的静态代理模式应用在我们的hook技术中。我们先复习一下静态代理模式

/** 
 * 定义Demo接口 
 */  
public interface Demo {
       
    public void save();  
}
/** 
 * DemoImpl实现Demo接口并覆写save()方法 
 * 真实主题,执行具体业务 
 */  
public class DemoImpl implements Demo {
       
    public void save() {  
        System.out.println("调用save()方法");  
    }  
}  
/** 
 * DemoImplProxy 也实现了Demo接口,并覆写了save()方法,增加了自己的业务  
 * 代理主题,负责其他业务的处理 
 */  
public class DemoImplProxy implements Demo {
       
    Demo demoImpl = new DemoImpl();  

    public void save() {  
        System.out.println("开始记录日志");  
        demoImpl.save();  
        System.out.println("开始结束日志");  
    }  
}  

我们看出来,代理是对原有功能的拓展,而且很多时候我们在开发的过程中并不能改变我们原有的功能,比如系统打电话,startActivity等等。这时候我们就想,如果我们对他们进行拓展,让他们添加我们自己的一些元素,是不是就可以达到意想不到的效果。所以我们就引出了Hook的概念。其实Hook就是干偷梁换柱之事。

项目代码

++分析在下面模块++

我先把项目写上去,然后我们在分析,这样我觉得比先一大堆理论要好。我们目的很简单就是让我们在startActivity的时候我们拓展一下我们的功能(打印一些信息)

首先实现自己的Application子类,原因是这里执行比较早

public class APP extends Application {
   
    @Override
    public void onCreate() {
        super.onCreate();
        setEvilInstrumentation();
    }

    public void setEvilInstrumentation() {
        try {
            //先获取到当前的ActivityThread对象
            Class<?> activityThreadClass = Class.forName("android.app.ActivityThread");
            Method currentActivityThreadMethod = activityThreadClass.getDeclaredMethod("currentActivityThread");//得到这个方法
            currentActivityThreadMethod.setAccessible(true);
            Object currentActivityThread = currentActivityThreadMethod.invoke(null);//此时得到的就是ActivityThread(因为在attach的时候调用赋值)

            Field mInstrumentationField = activityThreadClass.getDeclaredField("mInstrumentation");//得到ActvitiyThread中的mInstrumentation字段
            mInstrumentationField.setAccessible(true);
            Instrumentation mInstrumentation = (Instrumentation) mInstrumentationField.get(currentActivityThread);

            //创建代理对象
            EvilInstrumentation evilInstrumentation = new EvilInstrumentation(mInstrumentation,APP.this);
            mInstrumentationField.set(currentActivityThread, evilInstrumentation);//将系统中mInstrumentation换成自己的EvilInstrumentation
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

我们要替换的类EvilInstrumentation

public class EvilInstrumentation extends Instrumentation {
   

    private static final String TAG = "EvilInstrumentation";
    // ActivityThread中原始的对象, 保存起来
    Instrumentation mBase;
    private Context mContext = null;

    public EvilInstrumentation(Instrumentation base) {
        mBase = base;
    }

    public EvilInstrumentation(Instrumentation mInstrumentation, APP app) {
        this(mInstrumentation);
        mContext = app.getApplicationContext();
    }

    public ActivityResult execStartActivity(
            Context who, IBinder contextThread, IBinder token, Activity target,
            Intent intent, int requestCode, Bundle options) {

        Toast.makeText(mContext, "\n执行了startActivity, 参数如下: \n" + "who = [" + who + "], " +
                "\ncontextThread = [" + contextThread + "], \ntoken = [" + token + "], " +
                "\ntarget = [" + target + "], \nintent = [" + intent +
                "], \nrequestCode = [" + requestCode + "], \noptions = [" + options + "]", Toast.LENGTH_LONG).show();

        // 由于这个方法是隐藏的,因此需要使用反射调用;首先找到这个方法
        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) {
            throw new RuntimeException("需要重新适配了,framework层代码被谷歌改了");
        }
    }
}

MainActivity

public class MainActivity extends AppCompatActivity {
   
    private Button btn ;
    @Override
    protected void onCreate(Bun
  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值