语言小白为能够看懂的插件化DroidPlugin原理(二)– 反射机制与Hook入门

  前言:以上平等篇博文《小白为能够看懂的插件化DroidPlugin原理(一)–
动态代理》遇详尽介绍了
DroidPlugin
原理中涉嫌到之动态代理模式,看罢上篇博文后而就算见面发觉原本动态代理真的非常简单,只不过就是是贯彻一个
InvocationHandler 接口重写一下 invoke 方法而已。不错,其实过多看似 high
level
的艺还连没设想着之那晦涩难了解,只要你愿意下定狠心去探听她,去认识它,去上学她而就是会见意识,原来都是可效仿得清楚的。本篇博文将介绍
DroidPlugin 框架中不时因此到的另外两独知识点–反射机制及Hook技术。

拍打反馈:

  本系列文章的代码已经上传至github,下载地址:https://github.com/lgliuwei/DroidPluginStudy 本篇文章对应的代码在
com.liuwei.proxy_hook.reflect
和 com.liuwei.proxy_hook.hook.simplehook 包内。

【拍打让人软软】

同、反射机制

“你想哭就哭吧,在自身这边没有其它的羞涩,身心一体,一切影响都是正常的,”水一样说。

  1、反射是呀?

自己无清楚怎么了,趴在冲击打床上,接受它的拍打时,我莫名的纪念只要流泪,我对水一说:“你的各一样掌握看似无力倒渗透到五污染六腑,渗透及体内,仿佛有种植无形的力量于提拔自己身体的记忆与抑制住的心气,我禁不住想哭,但是可非理解哭点从何而来……”

  JAVA反射机制是当运行状态中,对于自由一个像样,都能够理解这个近乎的享有属性与办法;对于自由一个靶,都能够调用它的随机方法以及性能;这种动态获取信息以及动态调用对象方法的功力称为java语言的反光机制。

身体的每一个细胞都知情我们头脑里的所想所念。身体的另不适和疾病吗还来我们内在的信念。我们内在积压的伤心、愤怒、负面情绪越多,身体就是见面愈加轻染病。疾病是灵魂的语言,它于揭示我们内在的瘀堵。

  2、反射机制的图:

撞倒起了在动身时,我若清水洗都了带动满泥浆的身体,见她前面那种以压力所带的紧绷感与沉重感似乎为放,觉得从未有的人以及心灵的轻松,那种感觉不是按摩或推拿能够享有的痛快,这样的相撞起感觉好极了!

  (1)反射可以于运转时判断任意一个对象所属的类;

水一,是自我3年前人生低谷时认识的一致各项菇凉,虽然比自己小一些东,可是天生具有着特别的小聪明与慧根,每每在觀照自己內心出現焦慮的時候,我总会找到她失去小聚一下,而她呢终究能感受及我的心迹状态,这几年为其底影响为去阅读和体贴了众多有关性方面的书本和内容,也因为在其底砥砺与支撑给我做出了重重内在突破性尝试,并创造了祥和工作室,真的要命幸运人生里发出这般同样各项朋友。很开心之是在今年它吗开始用好之修行体验和想到开始与丁分享,开了自疗愈拍打工作室,这吗是如出一辙种人生美好吧!

  (2)反射可以当运转时组织任意一个类似的目标;

本人愿意以及时无异份幸运分享给您——我之心上人等,更愿意介绍为你这么平等各朋友,亦要你可去她那里以坐……

  (3)反射可以于运作时判断任意一个看似有的人身自由成员变量和艺术;

语言 1

  (4)反射可以于运转时调用任意一个接近的肆意方法;

语言 2

  (5)可以由此反射机制变动态代理。

先听说过,自己打大遥远不使打打师拍一不善。但从没论证过(这个是自之死,啥事一定要是论证,要验证)。

  3、Talk is cheap,show me the code. 来同样组反射机制小示例

其拍脸有个别个多月份了,收效甚微。我拍了相同差,痘痘消了许多。

  首先创建一个类供反射调用测试用,暂且将类名
BeReflected,并于接近吃补充加少独成员变量、三个一般方法、一个静态变量,一个静态方法,具体代码如下:

另外,调整了其底撞击于部位。脸是身体状况的反应,找到问题,针对性拍效果更精!

 1 /**
 2  * 被反射测试的类
 3  * Created by liuwei on 17/4/2.
 4  */
 5 public class BeReflected {
 6     private String field1 = "I am field1";
 7     private String field2 = "I am field2";
 8     private static String staticField = "I am staticField";
 9     private void method1(){
10         Logger.i(BeReflected.class, "I am method1");
11     }
12     private void method1(String param) {
13         Logger.i(BeReflected.class, "I am method1--param = " + param);
14     }
15     private void method2(){
16         Logger.i(BeReflected.class, "I am method2");
17     }
18     public static void staticMethod(){
19         Logger.i(BeReflected.class, "I am staticMethod");
20     }
21 }

——————————

  (1)通过反射获取 BeReflected 的Class类型,并拿那个初始化。(其中
Logger 是楼主封装的一个日记打印类,无需在完全这些细节)

【悄悄:拍打师的值】

1 // 1、通过反射获取BeReflected所属的类
2 Class<?> beReflectedClass = Class.forName("com.liuwei.proxy_hook.reflect.BeReflected");
3 Logger.i(ReflectTest.class, beReflectedClass);
4 
5 // 2、通过反射创建实例化一个类
6 Object beReflected = beReflectedClass.newInstance();
7 Logger.i(ReflectTest.class, beReflected);

犹如森医疗器械,拍打师也是一个细的疗愈管道,其效力,就在于那自身之僻静程度。

  输出如下:

来只个案说了,一不良空明拍打,相当给十几不行净心拍打,而同等不善净心拍打,可以抵上自己拍好几个月。

  [ReflectTest] : class
com.liuwei.proxy_hook.reflect.BeReflected
  [ReflectTest] :
com.liuwei.proxy_hook.reflect.BeReflected@7d4991ad

冲击,是同等的打。但可别,从性情,到渗透,到身和心灵的疗愈效果。

  (2)通过反射访问私有方法和民用成员变量,并转移私有变量的值。我们还亮,对于一个私类型的变量,在无供公开的
set 之类方法的事态下,想改它的价值是免容许的,但是下反射就可完成。

列一个恬静的打打师,都如相同贵也眼前的个案精密订制的疗愈机器,凭借觉知去直击病灶、化解污浊,重还身心的寂静本质。

 1 // 3、通过反射调用一个私有方法和成员变量
 2 Method method = beReflectedClass.getDeclaredMethod("method1");
 3 method.setAccessible(true);// 将此值设为true即可访问私有的方法和成员变量
 4 method.invoke(beReflected);// 访问普通成员变量和方法是需要在调用invoke方法是传入该类的对象
 5 
 6 Field field1 = beReflectedClass.getDeclaredField("field1");
 7 field1.setAccessible(true);
 8 Logger.i(ReflectTest.class, "field 改变前的值:" + field1.get(beReflected));
 9 field1.set(beReflected, "我是 field1 被改变后的值");
10 Logger.i(ReflectTest.class, "field 改变后的值:" + field1.get(beReflected));

拉开阅读:水一致拍打+聊愈室项目简介

  输出如下:  

本来律动疗法调理过程中的宽泛现象

  [BeReflected] : I am
method1
  [ReflectTest] : field
改变前的价值:I am field1
  [ReflectTest] : field
改变后底价:我是 field1 于转后底价值

关于本律动疗法的“痛”

   (3)通过反射访问静态方法和静态变量。访问静态方法和变量时不需要传入所属类的靶子,传入
null 即可访问。代码如下:

自我拍打链接:当冲击疗法网络视频全整理
(50管)

1 // 4、通过反射调用一个静态的方法和变量
2 Method staticMethod = beReflectedClass.getDeclaredMethod("staticMethod");
3 staticMethod.invoke(null);
4 
5 Field staticField = beReflectedClass.getDeclaredField("staticField");
6 staticField.setAccessible(true);
7 Logger.i(ReflectTest.class, staticField.get(null));

【自然律动拍起举报】
拍打让身心柔软

  输出如下:

【自然律动拍于只案】自性为师

  [BeReflected] : I am
staticMethod
  [ReflectTest] : I am
staticField

【自然律动疗法案例】调理妇科

  (4)通过反射访问一个牵动参数的办法。访问带参数的点子是,需要以
getDeclareMethod 后面传出一组参数的类别。

武汉|自然律动拍打公益活动首希望

1 // 5、通过反射访问一个带参数的方法
2 Method method1 = beReflectedClass.getDeclaredMethod("method1", String.class);
3 method1.setAccessible(true);
4 method1.invoke(beReflected, "我是被传入的参数");

【自然律动疗法案例】肾结石排掉

  输出如下:


自然律动疗法案例】肺肿瘤自己打好

  [BeReflected] : I am
method1–param = 我是于盛传的参数

【自然律动疗法案例】瘦了18斤

   (5)通过反射获取类中有的成员变量和办法。

【自然律动疗法案例】降低胰岛素

1 // 6、遍历类中所有的方法和成员变量
2 for (Method tempMethod : beReflectedClass.getDeclaredMethods()) {
3     Logger.i(ReflectTest.class, tempMethod.getName());
4 }
5 for (Field tempField : beReflectedClass.getDeclaredFields()) {
6     Logger.i(ReflectTest.class, tempField.getName());
7 }

打扮,祛斑的拍打方法

  输出如下:

瘦身:我是怎么样瘦25斤的?还有再牛之55龙瘦50斤

  [ReflectTest] :
method2
  [ReflectTest] :
method1
  [ReflectTest] :
method1
  [ReflectTest] :
staticMethod
  [ReflectTest] :
field1
  [ReflectTest] :
field2
  [ReflectTest] :
staticField

  看了上面几乎单例证之后,你是无是道反射还算神奇,可以好多用常规方式做不交的操作。当然者只是示例了映机制中不过核心的局部调用而已,感兴趣之对象可自动查阅官方文档。废话不多说了,我们赶快上马介绍
Hook 技术。

二、Hook入门

  Hook 中文释意是“钩子”,这片天楼主为直接在雕刻,Hook
到底指的是啊?如何才会为此平等栽简单容易亮,生动形象之诠释来提现 Hook
技术?以楼主目前本着 Hook
的领悟,通俗来拿就是通过某种手段对平码东西进行偷梁换柱,从而劫持目标来为达成控制目标的所作所为之目的。从技术角度来说,就是替换原有的对象,拦截目标函数/方法,从而改变该故的表现。

  于3月份初刚开上学 Hook
技术时写了一个有关替换汽车引擎的小例子,今天尽管管这事例贴出来吧。先说一下盖流程,首先我们见面起一个简约的汽车类,汽车类里面来只引擎的靶子,当然,汽车引擎都是发生正统的(这里就为接口),为简便起见,我们这边的汽车引擎标准且只来一个最好酷快之指标,后续我们见面由此反射机制来替换掉汽车引擎以达成增进极端要命快的目的。例子非常简单,通过者例子我们那个容易就能够开始的了解
Hook 技术。

  汽车类代码如下:

 1 /**
 2  * Created by liuwei on 17/3/1.
 3  */
 4 public class Car {
 5     private CarEngineInterface carEngine;
 6     public Car() {
 7         this.carEngine = new CarEngine();
 8     }
 9     public void showMaxSpeed(){
10         Logger.i(Car.class, "我卯足劲,玩命跑的最大速度可以达到:" + carEngine.maxSpeed());
11     }
12 }

  可以视,汽车类里面来一个 carEngine
(汽车发动机)的性能,汽车发动机接口代码如下:

1 /**
2  * 车引擎接口
3  * Created by liuwei on 17/3/1.
4  */
5 public interface CarEngineInterface {
6     int maxSpeed();
7 }

  汽车引擎类代码如下:

/**
 * 车引擎
 * Created by liuwei on 17/3/1.
 */
public class CarEngine implements CarEngineInterface {
    @Override
    public int maxSpeed() {
        return 60;
    }
}

  一个大概的小汽车搞定了,试跑一下:

1 public class Test {
2     public static void main(String[] args) {
3         Car car = new Car();
4         car.showMaxSpeed();
5     }
6 }

  输出结果:[Car] :
我卯足劲,玩命跑的极端充分快可达成:60

  额…好吧,卯足劲才能够跑至60,这发动机速度发出点….,作为一个飙车党,肯定不克忍心,必须改装!

  于改装之前,我们得事先考察从乌下手合适,可以望,在 Car
类里面有只 CarEngine 的目标,我们要开的哪怕是拿此 CarEngine
的靶子替换成我们团结一心创造的引擎类,这个引擎类需要有应声和 CarEngine
一样的表征,也就是说要贯彻 CarEngineInterface 接口或者直接接轨
CarEngine ,然后拦截到 maxSpeed
方法并修改返回值。那么这里我们其实有半点栽方案,一种植方案,可以重新创设一个引擎类,让其继承
CarEngine 或者实现 CarEngineInterface 都施行,然后经反射来替换 Car
对象吃的 carEngine 属性;另一样种方案,写一个动态代理,让其对 CarEngine
进行代理,然后据此反射替换。

  先是种方案:

  首先创建一个 EvilCarEngine 类, 详细代码如下:

 1 /**
 2  * Created by liuwei on 17/3/1.
 3  */
 4 public class EvilCarEngine extends CarEngine {
 5     private CarEngineInterface base;
 6     public EvilCarEngine(CarEngineInterface base) {
 7         this.base = base;
 8     }
 9     public int maxSpeed() {
10         return 3 * base.maxSpeed();
11     }
12 }

  然后用反射机制替换掉原来的汽车发动机。

 1 public class Test {
 2     public static void main(String[] args) {
 3         Car car = new Car();
 4         Logger.i(Test.class, "------------------替换前----------------");
 5         car.showMaxSpeed();
 6         // 怎样在不手动修改CarEngine类和Car类的情况下将大速度提高?
 7         try {
 8             Field carEngineField = Car.class.getDeclaredField("carEngine");
 9             carEngineField.setAccessible(true);
10             CarEngine carEngine = (CarEngine)carEngineField.get(car);
11             // 方法1
12             carEngineField.set(car, new EvilCarEngine(carEngine));
13         } catch (Exception e) {
14             e.printStackTrace();
15         }
16         Logger.i(Test.class, "------------------替换后----------------");
17         car.showMaxSpeed();
18     }
19 }

   输出语言结果:

  [Test] :
——————替换前—————-
  [Car] :
我卯足劲,玩命跑的不过充分快好上:60
  [Test] :
——————替换后—————-
  [Car] :
我卯足劲,玩命跑的最好老快好达标:180

  仲栽方案:

  首先创建一个动态代理类,并阻挠 maxSpeed 方法,修改返回值。

 1 /**
 2  * Created by liuwei on 17/3/1.
 3  */
 4 public class CarEngineProxyHandler implements InvocationHandler {
 5     private Object object;
 6     public CarEngineProxyHandler(Object object) {
 7         this.object = object;
 8     }
 9     @Override
10     public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
11         if ("maxSpeed".equals(method.getName())) {
12             Logger.i(CarEngineProxyHandler.class, "我是动态代理,我已拦截到 maxSpeed 方法,并偷偷返回了另一个值!");
13             return 180;
14         }
15         return method.invoke(object, args);
16     }
17 }

   同理,利用反射替换掉原来的汽车引擎

 1 public class Test {
 2     public static void main(String[] args) {
 3         Car car = new Car();
 4         Logger.i(Test.class, "------------------替换前----------------");
 5         car.showMaxSpeed();
 6         // 怎样在不手动修改CarEngine类和Car类的情况下将大速度提高?
 7         try {
 8             Field carEngineField = Car.class.getDeclaredField("carEngine");
 9             carEngineField.setAccessible(true);
10             CarEngine carEngine = (CarEngine)carEngineField.get(car);
11             // 方法2
12             CarEngineInterface carEngineProxy = (CarEngineInterface) Proxy.newProxyInstance(
13                     CarEngine.class.getClassLoader(), 
14                     new Class[]{CarEngineInterface.class}, 
15                     new CarEngineProxyHandler(carEngine));
16             carEngineField.set(car, carEngineProxy);
17 
18         } catch (Exception e) {
19             e.printStackTrace();
20         }
21 
22         Logger.i(Test.class, "------------------替换后----------------");
23         car.showMaxSpeed();
24     }
25 }

  输出结果以及方案一一致。

  写到此地,Hook 的主干用法也早就写了了,看罢例子之后,或许你已指向
Hook 有了一个骨干的认识,但值得一提的是,在 Test
类中的第10行代码中我们第一取出了 Car 中之 carEngine
对象,然后将这个目标传入了它的替罪羊中,为什么而这么做的,在替身中未传播
carEngine 或者重新 new 一个初的 CarEngine
不行也?这是一个要点,我们要掌握的凡,这里我们只是怀念修改一下引擎的无比酷快,而连无愿意引擎的任何性能被震慑,我们管从
Car 中取出原有的 carEngine
对象传入替身中,这样替身就得只选择我们关注的不二法门进行修改,对于我们无思改的方法直接调用传经来的
carEngine
对法即可。因为此地的例证为了简单从表现没增长其它的主意以及特性,所以就或多或少待重点说明一下。

三、小结

  其实 Hook 技术简单的话可以就此替换、拦截来描写,并不曾利用新技巧。Hook
本身并无碍事,它的难题在于你当针对相同段子代码 Hook 之前要摸索来一个当的 Hook
点,也就是说分析出由哪下手很关键,这便要求而对将要 Hook
的对象代码的实践流程很熟悉。本篇博文只是发端认识一下 Hook
技术,下同样篇博文将会晤介绍如何通过 Hook 技术阻碍 Android 中 startActivity
方法,并当分析的历程中牵线如何才是适量的 Hook
点。感兴趣之爱人可关注一下,敬请期待!

本文地址:http://www.cnblogs.com/codingblock/p/6642476.html

 

发表评论

电子邮件地址不会被公开。 必填项已用*标注

网站地图xml地图