這其實是前幾天看到 B 站代碼被開源后的一個感想,為什么要冒這么大風(fēng)險去做這事,活著不好嗎?到底是 996 讓你瘋狂?還是不給漲薪還克扣工資?或者黑了你的蔡徐坤?鬼知道為什么會有這想法。 然后腦子里就冒出了一個更奇怪的想法,如果我要在代碼里下毒,要怎么做?
如何在 Android 代碼中下毒
這其實是前幾天看到 B 站代碼被開源后的一個感想,為什么要冒這么大風(fēng)險去做這事,活著不好嗎?到底是 996 讓你瘋狂?還是不給漲薪還克扣工資?或者黑了你的蔡徐坤?鬼知道為什么會有這想法。
然后腦子里就冒出了一個更奇怪的想法,如果我要在代碼里下毒,要怎么做?
友情提示:如果你是一個管理者,或者一個項目的負(fù)責(zé)人,讀完以后請盡快去檢查你公司的代碼,小心被人下毒了。
Android 工程的幾個風(fēng)險
隨手寫一段奇葩代碼在項目中,這不算下毒,畢竟這種毒分分鐘就被查出來了,還有可能成為控訴你的證據(jù)。
要說下毒,首先要講的就是幾個容易下毒的點了。
- 現(xiàn)在的 Android 工程都是使用 Gradle 管理依賴庫了。但是 Gradle 有一個非常奇葩的特性,允許你依賴一個 snapshot 包,而這個特性正常情況下甚至是無法被關(guān)閉的(特殊情況走自定義除外)。
- ContentProvider 居然是可以自動執(zhí)行的,只要在 manifest 文件中聲明了你的 ContentProvider,并且保證這個 ContentProvider的 authorities 不會與其他的沖突,它的onCreate()方法就可以在應(yīng)用啟動的時候被自動執(zhí)行。當(dāng)然,沖突了你也裝不上。
- Android 保留了遠(yuǎn)程代碼執(zhí)行能力,盡管現(xiàn)在的插件化手段越來越困難,但那些也都是限制在系統(tǒng)組件層面,如果只是想單純的在遠(yuǎn)程執(zhí)行一段 helloworld 程序,這實在太簡單。
- Android 截至目前都沒有一個正常的,可以確保退出的方法(別告訴我System.exit()算你的正常退出)。而當(dāng)你調(diào)用System.exit()的時候,任何一個異常處理函數(shù)都不會有記錄,因為他特么就不是個異常。
- 原生函數(shù)居然可以讓 JAVAScript 直接調(diào)用,并且還沒任何權(quán)限問題,只要知道入口函數(shù),任何一個網(wǎng)頁的 js 都能調(diào)用。雖然 API17以后本地要加上 @JavaScriptInterface注解的,這已經(jīng)是進(jìn)步了。但是這貨他到現(xiàn)在居然都還是個 runtime 注解,結(jié)合第三條,其實沒什么鳥用。
- 我不想寫了,寫再多可能要出事了。
配毒藥
上面這幾條,隨便兩三點混合起來,都是致命的。畢竟,無形裝逼,最為致命。
舉個栗子:
我在職的時候,隨便在代碼里面丟個 jcenter 的 snapshot 包依賴,此刻這個包是沒有任何風(fēng)險的。 離職了以后,通過遠(yuǎn)端,覆蓋掉這個 snapshot 包,在關(guān)鍵代碼中下點毒,寫個異常或者上面說的 System.exit()。此刻,這個包就有風(fēng)險了。
稍微聰明一點,改進(jìn)一下,在依賴的時候依賴一個正式包。但是依賴的這個正式包,再去依賴一個 snapshot 包,同樣可行。
上面的步驟有個問題,就是這個關(guān)鍵的代碼,他本身有可能不會被執(zhí)行到。在改進(jìn)一下,在 snapshot 這個 aar 里用上第二條說的:用 ContentProvider 在應(yīng)用啟動的時候,就開始下毒,隨便開個線程,延遲個隨機(jī)數(shù),再根據(jù)時間戳做個取模,隨機(jī)一批用戶,調(diào)用System.exit(),不反編譯代碼,神仙來了也不知道包為什么莫名其妙就閃退了。
前面一種例子適合 snapshot 包的場景,經(jīng)常會有公司的打包機(jī)器是不允許連接外網(wǎng)的,其實很大程度就避免了這種問題。
只要你愿意,隨便網(wǎng)上丟一個class,再下載下來,通過ClassLoader直接 run 起來,一樣達(dá)到目的。
甚至你還可以限制再死一點,你公司在深圳,那就深圳的 IP 全部執(zhí)行默認(rèn)邏輯,外地 IP 才開始下毒。總之只有你想不到,沒有你辦不到。
最后
哦對了,git 的提交者信息也都是可以改的。
git config user.name(email)
放手干去吧,搞死那些 996 的公司,不會有證據(jù)的,別說是我教你的。