自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

另一種繞過(guò) Android P以上非公開API限制的辦法

移動(dòng)開發(fā) Android
去年發(fā)布的 Android P上引入了針對(duì)非公開API的限制,對(duì)開發(fā)者來(lái)說(shuō),這絕對(duì)是有史以來(lái)最重大的變化之一。前天 Google 發(fā)布了 Android Q 的 Beta 版,越來(lái)越多的 API 被加入了黑名單,而且 Google 要求下半年 APP 必須 target 28,這意味著現(xiàn)在的深灰名單也會(huì)生效。

去年發(fā)布的 Android P上引入了針對(duì)非公開API的限制,對(duì)開發(fā)者來(lái)說(shuō),這絕對(duì)是有史以來(lái)最重大的變化之一。前天 Google 發(fā)布了 Android Q 的 Beta 版,越來(lái)越多的 API 被加入了黑名單,而且 Google 要求下半年 APP 必須 target 28,這意味著現(xiàn)在的深灰名單也會(huì)生效;可以預(yù)見,在不久的將來(lái),我們要跟大量的 API 說(shuō)再見了。

[[259665]]

去年我給出了一種繞過(guò)Android P對(duì)非SDK接口限制的簡(jiǎn)單方法,經(jīng)驗(yàn)證,這辦法在 Android Q 的 Beta 版上依然能正常使用。雖然這個(gè)方法需要進(jìn)行內(nèi)存搜索,理論上有可能失敗,但實(shí)際上它曾在 VirtualXposed 和 太極 中得到了較為廣泛的驗(yàn)證,從未收到過(guò)由于反射失敗而導(dǎo)致問(wèn)題的反饋。而且據(jù)我所知,有若干用戶量不少的 APP 在線上使用了我提供的 FreeReflection 庫(kù),想來(lái)應(yīng)該也是沒(méi)有問(wèn)題的吧。

不過(guò)今天,我打算給出另外一種繞過(guò)限制的辦法。這個(gè)辦法目前來(lái)說(shuō)是***方案,我個(gè)人使用了一個(gè)多月,不存在任何問(wèn)題。

上次分析系統(tǒng)是如何施加這個(gè)限制 的時(shí)候,我們提到了幾種方式,最終給出了一種修改 runtime flag 的辦法;其中我們提到,系統(tǒng)有一個(gè) fn_caller_is_trusted 條件:如果調(diào)用者是系統(tǒng)類,那么就允許被調(diào)用。這是顯而易見的,畢竟這些私有 API 就是給系統(tǒng)用的,如果系統(tǒng)自己都被拒絕了,這是在玩錘子呢?

也就是說(shuō),如果我們能以系統(tǒng)類的身份去反射,那么就能暢通無(wú)阻。問(wèn)題是,我們?nèi)绾我浴赶到y(tǒng)的身份去反射」呢?一種最常見的辦法是,我們自己寫一個(gè)類,然后通過(guò)某種途徑把這個(gè)類的 ClassLoader 設(shè)置為系統(tǒng)的 ClassLoader,再借助這個(gè)類去反射其他類。但是這里的「通過(guò)某種途徑」依然要使用一些黑科技才能實(shí)現(xiàn),與修改 flags / inline hook 無(wú)本質(zhì)區(qū)別。

以系統(tǒng)類的身份去反射 有兩個(gè)意思,1. 直接把我們自己變成系統(tǒng)類;2. 借助系統(tǒng)類去調(diào)用反射。我們一個(gè)個(gè)分析。

「直接把我們自己變成系統(tǒng)類」這個(gè)方式有童鞋可能覺(jué)得天方夜譚,APP 的類怎么可能成為系統(tǒng)類?但是,一定不要被自己的固有思維給局限,一切皆有可能!我們知道,對(duì)APP來(lái)說(shuō),所謂的系統(tǒng)類就是被 BootstrapClassLoader 加載的類,這個(gè) ClassLoader 并非普通的 DexClassLoader,因此我們無(wú)法通過(guò)插入 dex path的方式注入類。但是,Android 的 ART 在 Android O 上引入了 JVMTI,JVMTI 提供了將某一個(gè)類轉(zhuǎn)換為 BootstrapClassLoader 中的類的方法!具體來(lái)說(shuō),我們寫一個(gè)類暴露反射相關(guān)的接口,然后通過(guò) JVMTI 提供的 AddToBootstrapClassLoaderSearch將此類加入 BootstrapClassLoader 就實(shí)現(xiàn)目的了。不過(guò),JVMTI 要在 release 版本的 APP 上運(yùn)行依然需要 Hack,所以這種途徑與其他的黑科技無(wú)本質(zhì)區(qū)別。

第二種方法,「借助系統(tǒng)的類去反射」也就是說(shuō),如果系統(tǒng)有一個(gè)方法systemMethod,這個(gè)systemMethod 去調(diào)用反射相反的方法,那么systemMethod毋庸置疑會(huì)反射成功。但是,我們從哪去找到這么一個(gè)方法給我們用?事實(shí)上,我們不僅能找到這樣的方法,而且這個(gè)方法能幫助我們調(diào)用任意的函數(shù),那就是反射本身!可能你已經(jīng)繞暈了,我解釋一下:

首先,我們通過(guò)反射 API 拿到 getDeclaredMethod 方法。getDeclaredMethod 是 public 的,不存在問(wèn)題;這個(gè)通過(guò)反射拿到的方法我們稱之為元反射方法。

然后,我們通過(guò)剛剛反射拿到元反射方法去反射調(diào)用 getDeclardMethod。這里我們就實(shí)現(xiàn)了以系統(tǒng)身份去反射的目的——反射相關(guān)的 API 都是系統(tǒng)類,因此我們的元反射方法也是被系統(tǒng)類加載的方法;所以我們的元反射方法調(diào)用的 getDeclardMethod 會(huì)被認(rèn)為是系統(tǒng)調(diào)用的,可以反射任意的方法。

偽代碼如下:

 

  1. Method metaGetDeclaredMethod = 
  2.         Class.class.getDeclaredMethod("getDeclardMethod"); // 公開API,無(wú)問(wèn)題 
  3. Method hiddenMethod = metaGetDeclaredMethod.invoke(hiddenClass, 
  4.         "hiddenMethod""hiddenMethod參數(shù)列表"); // 系統(tǒng)類通過(guò)反射使用隱藏 API,檢查直接通過(guò)。 
  5. hiddenMethod.invoke // 正確找到 Method 直接反射調(diào)用 

到這里,我們已經(jīng)能通過(guò)「元反射」的方式去任意獲取隱藏方法或者隱藏 Field 了。但是,如果我們所有使用的隱藏方法都要這么干,那還有點(diǎn)小麻煩。在 上文中,我們后來(lái)發(fā)現(xiàn),隱藏 API 調(diào)用還有「豁免」條件,具體代碼如下:

 

  1. if (shouldWarn || action == kDeny) { 
  2.     if (member_signature.IsExempted(runtime->GetHiddenApiExemptions())) { 
  3.       action = kAllow; 
  4.       // Avoid re-examining the exemption list next time
  5.       // Note this results in no warning for the member, which seems like what one would expect. 
  6.       // Exemptions effectively adds new members to the whitelist. 
  7.       MaybeWhitelistMember(runtime, member); 
  8.       return kAllow; 
  9.     } 
  10.     // 略     

只要 IsExempted 方法返回 true,就算這個(gè)方法在黑名單中,依然會(huì)被放行然后允許被調(diào)用。我們?cè)儆^察一下IsExempted方法:

 

  1. bool MemberSignature::IsExempted(const std::vector<std::string>& exemptions) { 
  2.   for (const std::string& exemption : exemptions) { 
  3.     if (DoesPrefixMatch(exemption)) { 
  4.       return true
  5.     } 
  6.   } 
  7.   return false

繼續(xù)跟蹤傳遞進(jìn)來(lái)的參數(shù) runtime->GetHiddenApiExemptions() 發(fā)現(xiàn)這玩意兒也是 runtime 里面的一個(gè)參數(shù),既然如此,我們可以一不做二不休,仿照修改 runtime flag 的方式直接修改 hidden_api_exemptions_ 也能繞過(guò)去。但如果我們繼續(xù)跟蹤下去,會(huì)有個(gè)有趣的發(fā)現(xiàn):這個(gè)API 竟然是暴露到 Java 層的,有一個(gè)對(duì)應(yīng)的 VMRuntime.setHiddenApiExemptions Java方法;也就是說(shuō),只要我們通過(guò) VMRuntime.setHiddenApiExemptions 設(shè)置下豁免條件,我們就能愉快滴使用反射了。

再結(jié)合上面這個(gè)方法,我們只需要通過(guò) 「元反射」來(lái)反射調(diào)用 VMRuntime.setHiddenApiExemptions 就能將我們自己要使用的隱藏 API 全部都豁免掉了。更進(jìn)一步,如果我們?cè)儆^察下上面的 IsExempted 方法里面調(diào)用的 DoesPrefixMatch,發(fā)現(xiàn)這玩意兒在對(duì)方法簽名進(jìn)行前綴匹配;童鞋們,我們所有Java方法類的簽名都是以 L開頭啊!如果我們把直接傳個(gè) L進(jìn)去,所有的隱藏API全部被赦免了!

詳細(xì)代碼在這里:https://github.com/tiann/FreeReflection

理論上講,這個(gè)方案不存在兼容性問(wèn)題。即使 ROM 刪掉了 setHiddenApiExemptions 方法,我們依然可以用「元反射」的方式去反射隱藏API,并且所有的代碼加起來(lái)不超過(guò)30行!當(dāng)然,如果 Google 繼續(xù)改進(jìn)驗(yàn)證隱藏API調(diào)用的方法,這個(gè)方式可能會(huì)失效;但是目前的機(jī)制沒(méi)有問(wèn)題。

文章的***,我想說(shuō)的是,本文的目的不是刻意去繞過(guò)限制。不給思維設(shè)限、不給人生設(shè)限,才會(huì)有更多可能。

責(zé)任編輯:未麗燕 來(lái)源: Weishu's Notes
相關(guān)推薦

2013-05-22 15:31:07

AOP的CGlib實(shí)現(xiàn)

2014-09-17 14:37:06

2018-04-18 07:34:58

2023-06-18 23:19:17

ChatGPTPPT方式

2010-07-21 16:23:09

運(yùn)行telnet程序

2011-12-29 21:28:31

Metro UI

2016-03-03 10:29:31

用戶信息改進(jìn)

2016-07-11 16:18:26

互聯(lián)網(wǎng)

2014-01-13 10:36:53

C++錯(cuò)誤

2019-01-02 08:04:29

GAN損失函數(shù)神經(jīng)網(wǎng)絡(luò)

2013-09-30 10:13:08

IT女程序員

2011-07-21 14:17:15

Ceylon

2010-09-02 09:14:35

CSS浮動(dòng)

2015-07-28 13:36:04

2009-06-17 09:05:05

Linux隱藏網(wǎng)絡(luò)鏈接命令

2013-10-21 15:11:15

OrmsqlOrm設(shè)計(jì)

2009-06-17 12:01:21

Linux

2010-06-09 16:17:20

TCP IP協(xié)議網(wǎng)絡(luò)故

2013-09-12 14:26:47

百度云網(wǎng)盤

2009-04-01 08:27:07

Opera瀏覽器
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)