如何在 Android 代码中下毒



对本文有任何问题,可加我的个人微信询问:kymjs123

如何在 Android 代码中下毒

这其实是前几天看到 B 站代码被开源后的一个感想,为什么要冒这么大风险去做这事,活着不好吗?到底是 996 让你疯狂?还是不给涨薪还克扣工资?或者黑了你的蔡徐坤?鬼知道为什么会有这想法。
然后脑子里就冒出了一个更奇怪的想法,如果我要在代码里下毒,要怎么做?

友情提示:如果你是一个管理者,或者一个项目的负责人,读完以后请尽快去检查你公司的代码,小心被人下毒了。

装逼

Android 工程的几个风险

随手写一段奇葩代码在项目中,这不算下毒,毕竟这种毒分分钟就被查出来了,还有可能成为控诉你的证据。
要说下毒,首先要讲的就是几个容易下毒的点了。

  1. 现在的 Android 工程都是使用 Gradle 管理依赖库了。但是 Gradle 有一个非常奇葩的特性,允许你依赖一个 snapshot 包,而这个特性正常情况下甚至是无法被关闭的(特殊情况走自定义除外)。
  2. ContentProvider 居然是可以自动执行的,只要在 manifest 文件中声明了你的 ContentProvider ,并且保证这个 ContentProvider 的 authorities 不会与其他的冲突,它的 onCreate() 方法就可以在应用启动的时候被自动执行。当然,冲突了你也装不上。
  3. Android 保留了远程代码执行能力,尽管现在的插件化手段越来越困难,但那些也都是限制在系统组件层面,如果只是想单纯的在远程执行一段 HelloWorld 程序,这实在太简单。
  4. Android 截至目前都没有一个正常的,可以确保退出的方法(别告诉我System.exit() 算你的正常退出)。而当你调用 System.exit() 的时候,任何一个异常处理函数都不会有记录,因为他特么就不是个异常。
  5. 原生函数居然可以让 JavaScript 直接调用,并且还没任何权限问题,只要知道入口函数,任何一个网页的 js 都能调用。虽然 API17 以后本地要加上 @JavascriptInterface 注解的,这已经是进步了。但是这货他到现在居然都还是个 runtime 注解,结合第三条,其实没什么鸟用。
  6. 我不想写了,写再多可能要出事了。

配毒药

上面这几条,随便两三点混合起来,都是致命的。毕竟,无形装逼,最为致命。

装逼

举个栗子:

我在职的时候,随便在代码里面丢个 jcenter 的 snapshot 包依赖,此刻这个包是没有任何风险的。 离职了以后,通过远端,覆盖掉这个 snapshot 包,在关键代码中下点毒,写个异常或者上面说的 System.exit()。此刻,这个包就有风险了。

稍微聪明一点,改进一下,在依赖的时候依赖一个正式包。但是依赖的这个正式包,再去依赖一个 snapshot 包,同样可行。

上面的步骤有个问题,就是这个关键的代码,他本身有可能不会被执行到。在改进一下,在 snapshot 这个 aar 里用上第二条说的:用 ContentProvider 在应用启动的时候,就开始下毒,随便开个线程,延迟个随机数,再根据时间戳做个取模,随机一批用户,调用 System.exit(),不反编译代码,神仙来了也不知道包为什么莫名其妙就闪退了。

前面一种例子适合 snapshot 包的场景,经常会有公司的打包机器是不允许连接外网的,其实很大程度就避免了这种问题。
只要你愿意,随便网上丢一个 class,再下载下来,通过 ClassLoader 直接 run 起来,一样达到目的。

甚至你还可以限制再死一点,你公司在深圳,那就深圳的 IP 全部执行默认逻辑,外地 IP 才开始下毒。然后你就发现总有用户报应用闪退,但是公司的人怎么也复现不出来,还想着是不是系统兼容性问题。总之只有你想不到,没有你办不到。

最后

哦对了,git 的提交者信息和提交时间也都是可以改的,随便改成一个已经离职的员工丢给他背锅没问题。

git config user.name(email)

放手干去吧,搞死那些 996 的公司,不会有证据的,别说是我教你的。

装逼