内容简介:之前写了篇检测多开的文章后,经过几个月的时间,基本上都已经被各多开软件绕过了。最近无意中发现了一些新特征,在特定环境下可以用来检测多开环境,特此来分享一下。某次在多开环境下运行demo,发现动态库加载失败了,错误信息如下:这个错误没什么好多说的,很明显,动态库是64位的而App运行在32位下,因此加载失败了。其实之前也看到过类似的现象,本应在64位下运行的App到多开环境下就变为32位环境了,只是之前并没有去深究,这次遇到后仔细想了一下,在某些情况下可以用来检测多开环境。
之前写了篇检测多开的文章后,经过几个月的时间,基本上都已经被各多开软件绕过了。最近无意中发现了一些新特征,在特定环境下可以用来检测多开环境,特此来分享一下。
起因
某次在多开环境下运行demo,发现动态库加载失败了,错误信息如下:
java.lang.UnsatisfiedLinkError: dlopen failed: "/data/app/【手动打码】/lib/arm64/【手动打码】.so" is 64-bit instead of 32-bit at java.lang.Runtime.loadLibrary0(Runtime.java:1016) at java.lang.System.loadLibrary(System.java:1660) ... 省略
这个错误没什么好多说的,很明显,动态库是64位的而App运行在32位下,因此加载失败了。其实之前也看到过类似的现象,本应在64位下运行的App到多开环境下就变为32位环境了,只是之前并没有去深究,这次遇到后仔细想了一下,在某些情况下可以用来检测多开环境。
解释
对于64位的手机,会启动2个zygote, zygote
和 zygote64
。
root 670 1 4359784 27292 poll_schedule_timeout 7f7b47058c S zygote64 root 671 1 1696576 11120 poll_schedule_timeout eb823684 S zygote
以64位运行的App将由 zygote64
fork而来,而以32位运行的App将由 zygote
fork出来。可以从下面的代码看出来, ZygoteProcess.java
中, startViaZygote
方法会通过 openZygoteSocketIfNeeded
方法选择合适的zygote。
private Process.ProcessStartResult startViaZygote(final String processClass, final String niceName, final int uid, final int gid, final int[] gids, int debugFlags, int mountExternal, int targetSdkVersion, String seInfo, String abi, String instructionSet, String appDataDir, String invokeWith, String[] extraArgs) throws ZygoteStartFailedEx { // 省略... synchronized (mLock) { return zygoteSendArgsAndGetResult(openZygoteSocketIfNeeded(abi), argsForZygote); } } @GuardedBy("mLock") private ZygoteState openZygoteSocketIfNeeded(String abi) throws ZygoteStartFailedEx { Preconditions.checkState(Thread.holdsLock(mLock), "ZygoteProcess lock not held"); if (primaryZygoteState == null || primaryZygoteState.isClosed()) { try { primaryZygoteState = ZygoteState.connect(mSocket); } catch (IOException ioe) { throw new ZygoteStartFailedEx("Error connecting to primary zygote", ioe); } } if (primaryZygoteState.matches(abi)) { return primaryZygoteState; } // The primary zygote didn't match. Try the secondary. if (secondaryZygoteState == null || secondaryZygoteState.isClosed()) { try { secondaryZygoteState = ZygoteState.connect(mSecondarySocket); } catch (IOException ioe) { throw new ZygoteStartFailedEx("Error connecting to secondary zygote", ioe); } } if (secondaryZygoteState.matches(abi)) { return secondaryZygoteState; } throw new ZygoteStartFailedEx("Unsupported zygote ABI: " + abi); }
那么如何确定App是以64位还是以32位运行呢?这就取决于动态库,如果只有32位的动态库(armeabi、armeabi-v7a),那么就会以32位运行,如果有64位的动态库(arm64-v8a),那么就以64位运行,不存在动态库则默认以64位运行。
如何证明?我们写3个demo来实际看一下。
-
demo1: 包名
top.darkness463.whichzygote
,不加动态库。 -
demo2: 包名
top.darkness463.zygote32
,加一个armeabi
动态库。 -
demo3: 包名
top.darkness463.zygote64
,加armeabi
和arm64-v8a
动态库。
root 670 1 4359784 27692 poll_schedule_timeout 7f7b47058c S zygote64 root 671 1 1696576 11416 poll_schedule_timeout eb823684 S zygote u0_a177 9878 670 4456080 63412 SyS_epoll_wait 7f7b47046c S top.darkness463.whichzygote u0_a180 13690 671 1791700 58664 SyS_epoll_wait eb8234ac S top.darkness463.zygote32 u0_a179 13871 670 4456524 64716 SyS_epoll_wait 7f7b47046c S top.darkness463.zygote64
可以看到,demo1和demo3的父进程是 zygote64
,而demo2的父进程是 zygote
。
那么为何在多开环境下会出现动态库加载失败的情况呢?原因就在于我那个demo有 arm64-v8a
的动态库,在安装时,系统会把该64位动态库拷到 /data/app/【包名】/lib/arm64/
下,然后那款多开软件只有32位的动态库,因此是以32位运行的,此时去 /data/app/【包名】/lib/arm64/
路径下加载64位的动态库必然导致失败。
打开思路的话,这也可以是一种检测多开环境的方式。
局限性
其实与其说这是检测多开的方法,倒不如说这是多开软件的bug。看了几款排名靠前的多开软件,都只有32位的动态库,但它们完全可以加上64位动态库来避免这个问题。
另外,为了减小apk的体积,绝大多数App只会添加 armeabi
平台,而不会添加 arm64-v8a
平台的动态库,所以这种检测方法在很多App上本身就是不成立的。
补遗
之前那篇文章提到过一个通过 /proc/self/maps
来检测多开的方式,当时提到这个方法的缺点是需要收集所有多开App的包名,但真正搞事的人很可能不会拿市面上的多开软件来作恶,他们可能利用开源的多开软件改成乱七八糟的包名,之前我甚至见过命名成 com.tencent.qqlite
来进行伪装的。之后我又做了一些工作,也和大家分享一下。
思路还是从 /proc/self/maps
中的动态库出发。在这里直接给出结论了不再详细讨论了。
-
/proc/self/maps
中出现包含/vbox/data/
、/shadow/data/
、/virtual/data/
的动态库,则运行在多开环境下。主要是因为很多多开软件都是基于开源或者抄来抄去的,所有目录名无外乎这么几种,但不排除会有多开软件修改掉名字的情况。 -
从
/proc/self/maps
加载的动态库路径我们可以解析到包名,如果自己的App并不会加载其他App的动态库(第三方登录可能会把其他App的动态库加载进去)的话,出现非自己包名的动态库可能疑似运行在多开环境下。服务端可以建立一套自动解析包名 + 添加到黑名单的流程。
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网
猜你喜欢:- Spring 内存木马检测思路
- 行人检测新思路:高级语义特征检测取得精度新突破
- CVPR 2019 | CSP行人检测:无锚点框的检测新思路
- ECCV 2018 | CornerNet:目标检测算法新思路
- CVPR 2020丨MAML-Tracker: 用目标检测思路做目标跟踪? 小样本即可得高准确率
- 高性能服务器架构思路,不仅是思路
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
数值方法和MATLAB实现与应用
拉克唐瓦尔德 / 机械工业出版社 / 2004-9 / 59.00元
本书是关于数值方法和MATLAB的介绍,是针对高等院校理工科专业学生编写的教材。数值方法可以用来生成其他方法无法求解的问题的近似解。本书的主要目的是为应用计算打下坚实的基础,由简单到复杂讲述了标准数值方法在实际问题中的实现和应用。本书通篇使用良好的编程习惯向读者展示了如何清楚地表达计算思想及编制文档。书中通过给读者提供大量的可直接运行的代码库以及讲解MARLAB工具箱中内置函数使用的数量方法,帮助......一起来看看 《数值方法和MATLAB实现与应用》 这本书的介绍吧!