一種繞開反病毒引擎的方法

前段時間,我整出了一個 無需Root也能使用Xposed 的方法,簡單來說,就是通過 雙開技術(VirtualApp)結合本進程內的Java Method Hook(epic)實現載入Xposed模塊,從而任意修改內部App的方法。項目剛 開源 不久,有大量用戶指責 VirtualXposed 是惡意軟體,有病毒!比如說:

  • VirusTotal says you have malware · Issue #10 · android-hacker/VirtualXposed
  • McAfee報毒 · Issue #21 · android-hacker/VirtualXposed
  • Galaxy Note8設備維護中提示對設備有害 · Issue #8 · android-hacker/VirtualXposed

以及 VirusTotal的檢測結果:

(檢測報告地址:VirusTotal )

我當時不以為然,所以沒放在心上;畢竟沒有什麼病毒能這麼明目張胆公開把自己的代碼放出來給別人用吧?

直到後來,面對部分XDA用戶的質疑,以及一些國外媒體的報道,我意識到,在部分用戶眼中,「病毒」這個詞對他們非常敏感,16家殺毒引擎說你有病毒,就算你覺得清者自清,別人也是敬而遠之。於是我就開始了「洗脫罪名」之旅。

剛開始的時候我也是無從下手,去網上搜索這些病毒的名字,什麼 `Android:Agent-QBQ [PUP]`, `Tool.SilentInstaller.6.origin` 基本沒有什麼有意義的結果;整個代碼那麼多,怎麼判斷是哪一部分有問題,我到底應該從哪裡查起?

然後我就找了幾個做過病毒分析的工程師聊了聊,他們告訴我,目前一般對Android APK的靜態分析方法是採用特徵分析,就是提取你APK安裝包裡面的特徵,然後拿起和病毒庫做比對,如果有匹配,那麼就認為你可能是有害程序。

於是我就想,如果我是病毒分析工程師,我應該提取哪些特徵呢?動態載入代碼,運行可執行文件,敏感包名?順著這個想法,我做了幾件事:

  1. VirtualApp中有大量的 `odex`, `dex` 等字元串,針對這些串用硬編碼的base64加密串替代,運行時解密然後使用。
  2. 把所有硬編碼的類名,如微信,QQ裡面的類(對這些App做過特殊處理)也用base64串代替。
  3. 修改manifest中註冊的組件名,避免被匹配為VirtualApp。

這麼做之後,依然有14家反病毒引擎認為是病毒(少了2家);當時我有點懵,心裡一萬隻草泥馬奔騰而過。。。

這麼光靠猜實在不是辦法,需要有一種科學的方法去分析和解決這個問題。既然我們知道殺毒引擎會匹配特徵,正向去猜測它提取的特徵行不通,那麼我們可以反過來,看看什麼「東西」會命中它的哪些特徵。具體來說,APK文件分為幾個部分:Manifest,資源,dex文件(Java代碼),so文件(native 代碼)以及其他文件;我們可以把APK中的一部分文件剔除,然後把這個缺失某部分的APK文件拿去給反病毒引擎檢測,如果前後檢測結果有不同,那麼說明被剔除的那部分可能就是命中了某些病毒的特徵,從而被誤判。當然,這種方法不一定正確,這取決於殺毒引擎如何提取特徵;但是可以一試。

嘗試之後發現,只有java code才會導致殺毒引擎被判為病毒;其他之前猜想的manifest組件,so文件實際上都沒有問題。那麼,到底是哪部分Java代碼被判為有問題呢?起初我打算從依賴庫的角度去做代碼剔除,不過立馬就被否定了——雖然我依賴了十幾個三方庫,但是很顯然,很有可能查到最後會發現 VirtualXposed 本身的代碼才是被判為病毒的根源。最後,我使用的方法是這樣的:

  1. 取出所有的Java類,根據全限定名排序。
  2. 按順序刪掉一半的類,然後打包成APK給反病毒引擎檢測;如果有變化,那麼說明被刪的那部分類有問題;於是用被刪的那部分類再做二分(再刪除一半)繼續檢測,直到被鎖定為一個或幾個特定的類。如果沒有變化,那用同樣的辦法對保留的那部分類做二分。
  3. 鎖定到某些特定的類還不夠,最好能鎖定到具體的行。於是,我們可以繼續以方法為粒度進行二分測試,直到定位到所有的方法。

但是,光有思路是不行的。具體如何實施這個方案呢?你要刪除一半的類,怎麼刪?很顯然,如果直接刪Java源碼,是無法編譯成功拿到最終的apk文件的。我們應該對編譯產物做處理。在D8編譯器出來之前,APK的打包流程是這樣的:

觀察Java 源碼以及第三方庫被打包為dex的過程,我們可以知道,刪除被編譯過後的class文件是可以達到目的的;而如果要控制這個過程,gradle的Transform API是個極佳的選擇。

另外,其實還有一條路:Android虛擬機有一套自己的虛擬機指令smali,我們也可以反編譯APK得到smali文件,刪掉部分smali文件然後重打包;這樣也可以達到目的,不過由於 gradle Transform API的存在,刪class文件的過程實現起來簡單很多,並且可操作性也強很多;再結合位元組碼操作工具,我們可以對apk做各種修改來試探反病毒引擎。

最終使用的代碼在這:fuck_anti_virus.gradle。這是一個gradle插件,在項目裡面直接引用即可。

經過數天對16個反病毒引擎的探測,我解決了所有被誤報的問題;最終的檢測結果長這樣:

不過這裡面被誤判為病毒的代碼,實在是讓人啼笑皆非。不妨來看一下:

1. 敏感API調用, `openDexFileNative`, `openDexFile`,用base64編碼解決

2. 敏感API調用,`System.setProperty`,通過用反射調用繞過

3. 列印日誌以及異常堆棧被誤判(這個我沒弄清楚原因,有點莫名其妙)

4. 替換Mainifest組件名

5. 修改類名,修改輸入日誌的姿勢

如果第一個和第二個還能扯得上點關係,後面那幾個以及我其他的修改,我想說,不是我針對誰,這些反病毒引擎簡直都是智障。。。

然後分享一個最近無意中發現的代碼:

這是某雙開軟體,動態載入的插件逆向之後的代碼。剛開始看到的時候,我驚呆了。這尼瑪是在直接查被雙開的微信內部的資料庫啊!我記得之前說過,雙開軟體是非常不安全的,雙開軟體本身對內部的APP有著完全的控制權,而且雙開內部的APP對其他被雙開APP的數據有著完全的訪問權(比如說你在裡面裝了一個惡意軟體,這個軟體可以訪問微信,支付寶的所有數據;所以把雙開軟體成為沙盒是不恰當的,這裡面並不安全)。但是我沒想到,竟然真的有人這麼做,而且還是雙開軟體自己乾的。但如果你把這個軟體丟到殺毒軟體裡面檢測呢,沒錯,很安全。就連 `Android:Agent-QBQ [PUP]`(Potentially Unwanted Program) 都沒有。

最後我還是想說,現在的反病毒引擎真的是弱雞。當然也可能是因為 VirusTotal是免費的,各大殺毒引擎給出的API都是比較弱雞的版本,非常歡迎各路安全工程師前來打臉 ^_^ 還有,使用雙開軟體以及Xposed等功能的時候,一定要注意安全哦~


推薦閱讀:

燒烤趴大家可曾盡興?11月18幾維安全依舊等你!
Android安全技術周報 08.18 - 08.25
移動APP漏洞自動化檢測平台建設
Android安全技術周報 09.29 - 10.12

TAG:科技 | Android | 移動安全 |