Android 繞過反射黑名單的方法
限制原理
Google 從 Android P 開始引入了針對非公開 API 的限制,這一點可以從 Native 相關(guān)的源碼中找到限制的原理,從而從中找到解決辦法,不過非必要原因不太建議去挑戰(zhàn)這種限制,畢竟不清楚在后續(xù)的版本中會不會做限制,維護(hù)起來挺麻煩的。
在 Native 層有幾個訪問級別:
class HiddenApiAccessFlags { public: enum ApiList { kWhitelist = 0, kLightGreylist, kDarkGreylist, kBlacklist, }; }
另外還有幾個對應(yīng)的響應(yīng)級別:
enum Action { kAllow, //通過 kAllowButWarn, //通過,但日志警告 kAllowButWarnAndToast, //通過,且日志警告和彈窗 kDeny //拒絕訪問 };
這里介紹一下網(wǎng)上的一些解決方式,此外,還可以把我們調(diào)用了反射方法的類的類加載器設(shè)置為系統(tǒng)類加載器,這樣就可以繞過 Native 層的限制了。
系統(tǒng)類偽裝
黑名單在系統(tǒng)中有一個 fn_caller_is_trusted 的條件:如果調(diào)用者是系統(tǒng)類,那么就允許被調(diào)用。即如果我們能以系統(tǒng)類的身份去反射,那么就能暢通無阻:
- 首先通過反射 API 拿到 getDeclaredMethod 方法。getDeclaredMethod 是 public 的,不存在問題;這個通過反射拿到的方法網(wǎng)上稱之為元反射方法。
- 然后通過剛剛的元反射方法去反射調(diào)用 getDeclardMethod。這里我們就實現(xiàn)了以系統(tǒng)身份去反射的目的——反射相關(guān)的 API 都是系統(tǒng)類,因此我們的元反射方法也是被系統(tǒng)類加載的方法;所以我們的元反射方法調(diào)用的 getDeclardMethod 會被認(rèn)為是系統(tǒng)調(diào)用的,可以反射任意的方法。
偽代碼如下:
// 公開API,無問題 Method metaGetDeclaredMethod = Class.class.getDeclaredMethod("getDeclardMethod"); // 系統(tǒng)類通過反射使用隱藏 API,檢查直接通過。 Method hiddenMethod = metaGetDeclaredMethod.invoke(hiddenClass, "hiddenMethod", "hiddenMethod參數(shù)列表"); // 正確找到 Method 直接反射調(diào)用 hiddenMethod.invoke
豁免條件
隱藏 API 的調(diào)用有「豁免」條件,即只要它是豁免的,則即使它在黑名單中,也會被放行。這種方式暴露給了 Java 層,因此可以通過 VMRuntime.setHiddenApiExemptions 方法來實現(xiàn)。再結(jié)合上面這個方法,我們只需要通過 「元反射」 來反射調(diào)用 VMRuntime.setHiddenApiExemptions 就能將我們自己要使用的隱藏 API 全部都豁免掉了。另外系統(tǒng)在檢查豁免時是通過方法簽名進(jìn)行前綴匹配的,而 Java 方法簽名都是 L 開頭的,因此我們可以把直接傳個 L 進(jìn)去,那么所有的隱藏API全部被赦免了!
源碼直接參考網(wǎng)上大佬的開源項目: FreeReflection。
public final class BootstrapClass { private static final String TAG = "BootstrapClass"; private static Object sVmRuntime; private static Method setHiddenApiExemptions; static { if (SDK_INT >= Build.VERSION_CODES.P) { try { Method forName = Class.class.getDeclaredMethod("forName", String.class); Method getDeclaredMethod = Class.class.getDeclaredMethod("getDeclaredMethod", String.class, Class[].class); Class<?> vmRuntimeClass = (Class<?>) forName.invoke(null, "dalvik.system.VMRuntime"); Method getRuntime = (Method) getDeclaredMethod.invoke(vmRuntimeClass, "getRuntime", null); setHiddenApiExemptions = (Method) getDeclaredMethod.invoke(vmRuntimeClass, "setHiddenApiExemptions", new Class[]{String[].class}); sVmRuntime = getRuntime.invoke(null); } catch (Throwable e) { Log.w(TAG, "reflect bootstrap failed:", e); } } } /** * make the method exempted from hidden API check. * * @param method the method signature prefix. * @return true if success. */ public static boolean exempt(String method) { return exempt(new String[]{method}); } /** * make specific methods exempted from hidden API check. * * @param methods the method signature prefix, such as "Ldalvik/system", "Landroid" or even "L" * @return true if success */ public static boolean exempt(String... methods) { if (sVmRuntime == null || setHiddenApiExemptions == null) { return false; } try { setHiddenApiExemptions.invoke(sVmRuntime, new Object[]{methods}); return true; } catch (Throwable e) { return false; } } /** * Make all hidden API exempted. * * @return true if success. */ public static boolean exemptAll() { return exempt(new String[]{"L"}); } }
以上就是Android 繞過反射黑名單的方法的詳細(xì)內(nèi)容,更多關(guān)于Android 繞過反射黑名單的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
TextInputLayout輸入框控件的懸浮標(biāo)簽
這篇文章主要為大家詳細(xì)介紹了TextInputLayout輸入框控件的懸浮標(biāo)簽,具有一定的參考價值,感興趣的小伙伴們可以參考一下2017-12-12Android Compose實現(xiàn)伸縮ToolBar的思路詳解
這篇文章主要介紹了Android Compose之伸縮ToolBar的實現(xiàn),本文給大家分享主要實現(xiàn)思路及實現(xiàn)過程,通過實例代碼給大家介紹的非常詳細(xì),需要的朋友可以參考下2021-10-10Android基于注解的6.0權(quán)限動態(tài)請求框架詳解
這篇文章主要介紹了Android基于注解的6.0權(quán)限動態(tài)請求框架詳解,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2018-04-04android手機(jī)獲取gps和基站的經(jīng)緯度地址實現(xiàn)代碼
android手機(jī)如何獲取gps和基站的經(jīng)緯度地址,疑問,于是網(wǎng)上搜集整理一些,拿出來和大家分享下,希望可以幫助你們2012-12-12SQLSERVER實現(xiàn)更改表名,更改列名,更改約束代碼
這篇文章主要介紹了SQLSERVER實現(xiàn)更改表名,更改列名,更改約束代碼的相關(guān)資料,需要的朋友可以參考下2016-03-03Android控件FlowLikeView實現(xiàn)點贊動畫
這篇文章主要為大家詳細(xì)介紹了一個點贊動畫的優(yōu)雅控件FlowLikeView,具有一定的參考價值,感興趣的小伙伴們可以參考一下2018-06-06