教你一種繞過谷歌禁止反射的方法

Android入墳之路發表於2019-04-08

Androi P之後Google可能會禁止使用反射來獲取隱藏方法的呼叫,雖然在preview版本中只會以log的形式提示,但後續的版本可能會在使用反射時直接丟擲錯誤。

這裡提供其中一種破解反射禁止的方法,不過這種方法也有侷限,就是隻能用於本來已經是public或者static的隱藏方法。
對於這種型別的隱藏方法,我們之前的解決途徑是通過反射來獲取,因為雖然是public,但是方法被@hidden註解過,所以沒法直接呼叫。
但雖然不能用反射,直接呼叫卻是可以的。這就是具體的思路。

一、關於隱藏方法

我們知道在Android原始碼中有部分程式碼是不允許開發者使用的,這裡要分兩種情況。
· 沒有打包進android.jar的類和方法,這部分不是隱藏的
· 打包進android.jar裡的隱藏類和方法

如果檢視原始碼,會發現有很多程式碼其實沒有打進android.jar,比如internal包下的類,其中就有WindowManagerService。
這部分類之所以不打進android.jar,目的是這些類是隻給android內部使用的,不希望開發者使用。

今天只說明對於沒有打包進 android.jar的類,在不用反射的情況下的使用方法。

二、用provided的方式提供丟失的類

在gradle專案裡,可以用provided的方式引入 java library,這樣引入的library不會被打包進最終的apk裡。
在gradle中這麼寫,

dependencies {
    provided project(':libhookandroid')
}
複製程式碼

舉個例子,比方這時候要用 ActivityThread,這裡面有個 public方法 currentActivityThread(),我們要呼叫它,那麼可以在lib專案下按報名建一個類

public class ActivityThread{
    public static ActivityThread currentActivityThread(){
        return null;
    }
}
複製程式碼

為何可以return null呢?
因為它不會最終編譯進apk,執行時呼叫的仍然是Android裡的ActivityThread,那裡有真正的實現邏輯,我們這裡只是做了個殼用來保證編譯時不會有問題。
寫完lib後在主工程裡就可以直接呼叫了,

    ActivityThread thread = ActivityThread.currentActivityThread();
複製程式碼

因為是public方法,所以也不需要反射。

三、總結

對於Android裡沒有被打進 android.jar包中的類,可以通過 provided library的方式提供呼叫,
雖然P禁用了反射,但是直接呼叫是可以的。
然而缺點也是很明顯,它不能用到 protected或者 private的方法。
對於其他的情況,我們可以通過修改apk的class loader改成 BootStrapClassLoader來實現繞過這個限制。
看過之前文章的朋友應該知道 BootStrapClassLoader是終極 ClassLoader,以後我們會介紹通過它來繞過限制的方法。


相關文章