Android 如何優雅的hook私有方法

Android 如何優雅的hook私有方法

最近在使用java寫反射進行hook系統的方法,但是每次都會寫一長串代碼,各種try catch,着實讓人的着急,偶然間想起來從一個開源庫裏看到的一個類,當時沒看懂,就保存了下來,現在回頭看看居然很有意思

Hack.java

就是這個類

有幾大特性

  • 鏈式調用
  • 簡潔,清晰

下面我們來看這個類的使用方法

首先放一個類,咱們就來hack這個類

package com.utils.dddemo.hack;
import android.util.Log;
import com.utils.library.log.LogA;
public class HackDemo {
    private int mIntField;
    private String mStr;
    private static String staticField = "dds";
    // 構造方法
    private HackDemo() {
        Log.d("dds", "constructor");
    }
    private HackDemo(int x) {
        mIntField = x;
        Log.d("dds", "constructor " + x);
    }
    private HackDemo(int x, String str) {
        mIntField = x;
        mStr = str;
        Log.d("dds", "constructor " + x);
    }
    
     // 成員方法
    private int foo() {
        Log.d("dds", "method :foo");
        // 返回私有變量
        return mIntField;
    }
    private int foo(int type, String str) {
        Log.d("dds", "method :foo " + type + "," + str);
        return 7;
    }
    
    // 靜態成員方法
    private static void bar() {
        Log.d("dds", "static method :bar");
    }
    private static int bar(int type) {
        Log.d("dds", "static method :bar " + type);
        return type;
    }
    private static void bar(int type, String name, Bean bean) {
        LogA.d("dds", "static method :bar type:%d,%s,%s", type, name, bean.toString());
    }
    
    // 打印靜態成員變量
    public void printStaticField() {
        Log.d("dds_test", "printStaticField:" + staticField);
    }
}

私有構造方法

無參數構造方法

        構造
		Hack.HackedMethod0 constructor = Hack
                .into("com.utils.dddemo.hack.HackDemo")
                .constructor()
                .withoutParams();
		// check
        assertNotNull(constructor);
		// 調用
        Object statically = constructor
                .invoke()
                .statically();
		// check
        assertNotNull(statically);

有參數構造方法

  		// 構造
		Hack.HackedMethod1 constructor1 = Hack
                .into("com.utils.dddemo.hack.HackDemo")
                .constructor()
                .withParam(int.class);
        // check
        assertNotNull(constructor1);
        // 調用
        Object statically1 = constructor1
        		.invoke(1222)
            	.statically();
        // check
        assertNotNull(statically1);

私有成員方法

無參數成員方法

        Hack.HackedMethod1 constructor1 = Hack
                .into("com.utils.dddemo.hack.HackDemo")
                .constructor()
                .withParam(int.class);
		// check
        assertNotNull(constructor1);
		// 構造方法
        Object statically1 = constructor1.invoke(1222).statically();
     	// check
        assertNotNull(statically1);
        
		// 構造該方法
        Hack.HackedMethod0 foo = Hack
                .into("com.utils.dddemo.hack.HackDemo")
                .method("foo")
                .returning(int.class)
                .withoutParams();
		// check
        assertNotNull(foo);
        
 		// check 返回值是否等於傳入的值
        assertEquals(1222, (int) foo.invoke().on(statically1));

有參數,有返回值方法

        Hack.HackedMethod1 constructor1 = Hack
                .into("com.utils.dddemo.hack.HackDemo")
                .constructor()
                .withParam(int.class);

        assertNotNull(constructor1);

        Object statically1 = constructor1.invoke(1222).statically();

        assertNotNull(statically1);

        Hack.HackedMethod2 foo = Hack
                .into("com.utils.dddemo.hack.HackDemo")
                .method("foo")
                .returning(int.class)
                .withParams(int.class, String.class);

        assertNotNull(foo);

        assertEquals(7, (int) foo.invoke(11, "dds_test").on(statically1));

私有靜態方法

無參數靜態方法

Hack.HackedMethod0 method = Hack
                .into("com.utils.dddemo.hack.HackDemo")
                .staticMethod("bar")
                .withoutParams();
        assertNotNull(method);
		// 方法調用
        method.invoke().statically();

有參數靜態方法

        Hack.HackedMethod3 method
                = Hack.into("com.utils.dddemo.hack.HackDemo")
                .staticMethod("bar")
                .throwing(IOException.class)
                .withParams(int.class, String.class, Bean.class);

        assertNotNull(method);
		// 調用方法
        method.invoke(-1, "xyz", new Bean()).statically();

下面重點來了,我們經常hook系統的方法都是hook的靜態成員變量,那我們該如何修改靜態成員變量的呢?

靜態成員變量

		Hack.HackedTargetField field = Hack
			.into("com.utils.dddemo.hack.HackDemo")
    		.staticField("staticField")
    		.ofType(String.class);
		//設置新值
        field.set("dds111111111");
		
		//打印出新值
        Hack.HackedMethod0 constructor = Hack
                .into("com.utils.dddemo.hack.HackDemo")
                .constructor()
                .withoutParams();

        assertNotNull(constructor);
        
        Object statically = constructor.invoke().statically();
        ((HackDemo) statically).printStaticField();

打印出結果

D/dds_test: printStaticField:dds111111111

代碼收錄

https://github.com/ddssingsong/AnyTool

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章