首页 > 编程知识 正文

如何实现游戏多开,如何实现多平台直播

时间:2023-05-03 07:40:11 阅读:231828 作者:4059

目录: 1. Android UID 介绍2. 多开基本原理3. 常用的多开方案4. VirtualAPP 如何实现多开

 

1. Android UID 介绍

Android 系统中修改了 Linux 的 UID 的含义。由于 Android 是单用户系统,不需要支持多用户登陆,因此传统的 UID 系统就失去了原来的意义。Android 的开发者巧妙地修改了 UID 的含义:每个 APP 对应一个 UID—用 UID 对应用程序进行管理。

Android 中查看 UID 的方法:

adb shell ps | grep 包名

 

2. 多开基本原理

通过在宿主容器上面新建一个进程供插件 APK 寄宿,然后通过 hook 一些系统接口欺骗应用—让虚拟化后应用以为自己是正常运行的独立 APP,欺骗系统—让系统认为此虚拟化应用是一个已正常安装在系统的应用。


UID 是一个虚拟化无法绕过的东西,不同于传统 linux 上的含义,因为 Android 是单用户系统,因此传统的 UID 失去了原来的意义,但是 Android 巧妙的修改了 UID 的含义:UID 是系统分配的一个应用的标志,每一个 APP 对应一个 UID。因为虚拟化并没有真正的安装应用,因此 UID 必定是和宿主一致的。

虚拟化将文件访问也做了虚拟化,因此虚拟化后的应用必定是有自己的 ”/data/data/pkg” 私有目录的。那么这样就有一个冲突的地方了,”/data/data” 目录下会为已安装的应用创建一个私有目录,并且只创建一个。那么如果一个 UID 下面有两个进程,进程名对应包名,而包名对应的 ”/data/data” 私有目录有两个可以访问,那是不是就和只为一个应用创建唯一一个私有目录相冲突了。 

 

 

3. 常用的多开方案

(1) 修改 APK

反编译 APK,修改 APK 包名、签名,将 APK 伪装成另外一个不同的 APK,但对于一些有加密的 APK,可能没办法实现。

产品:克隆大师

(2)  修改 Framework

对于有系统修改权限的厂商,可以修改 Framework 来实现双开的目的。本质是基于原生 Android 系统的多账户体系实现在不同的账户下登录不同的微信。

缺点在于成本较高,需要一个支持多账户的手机才可以,而国内 ROM 一般都把这个功能从表面上“阉割”了。此外,双开时还需要频繁切换系统账户,且不能同时收消息,极为不便。更加遗憾的是除分身外,基本没有其他功能。各个分身账户之间相互隔离,互不影响。

产品:小米应用分身、360奇酷手机

(3) 通过虚拟化技术实现

虚拟 Framework 层、虚拟文件系统、模拟 Android 对组件的管理、虚拟应用进程管理等一整套虚拟技术,将 APK 复制一份到虚拟空间中运行

产品:360 分身大师、LBE 空间、VirtualAPP

(4) 以插件机制运行

可以在无需安装、修改的情况下运行 APK 文件,利用反射替换,动态代理,hook 了系统的大部分与 system—server 进程通讯的函数,以此作为“欺上瞒下”的目的,欺骗系统“以为”只有一个 apk 在运行,瞒过插件让其“认为”自己已经安装。

产品:DroidPlugin、VirtualAPP

 

 

4. VirtualAPP 如何实现多开

我们先用 VirtualAPP 安装两个 58App:

然后我们可以看到 VirtualAPP 的 data 目录下:

VirtualAPP 通过 native hook 技术对文件系统也做了 hook (下章重点),  可以看到,它给两个 58App 分配了两个 user.

com.docker/virtual/data/system/users/0.xml:

<?xml version='1.0' encoding='utf-8' standalone='yes' ?><user id="0" serialNumber="0" flags="19" created="0" lastLoggedIn="0"> <name>Admin</name></user>

com.docker/virtual/data/system/users/1.xml:

<?xml version='1.0' encoding='utf-8' standalone='yes' ?><user id="1" serialNumber="1" flags="2" created="1619678812614" lastLoggedIn="0"> <name>Space 2</name></user>

com.docker/virtual/data/system/users/userlist.xml:

<?xml version='1.0' encoding='utf-8' standalone='yes' ?><users nextSerialNumber="2" version="0"> <user id="0" /> <user id="1" /></users> 我们通过 VirtualAPP 打开 两个 58App,查看对应的 uid: kuangzhongwen@MacBook-Pro-5 ~ % adb shell; topu0_a1865 6183 672 1497260 167416 0 0 S com.wubau0_a1865 6183 672 1497260 167416 0 0 S com.wubau0_a1865 3549 672 1501000 185600 0 0 S com.dockeru0_a1865 3798 672 1423680 106348 0 0 S com.docker:x

uid 是一样的,说明系统认为只打开了一个 App(VirtualAPP). VirtualApp 通过虚拟化技术和插件运行结合的方式,hook 了系统的大部分与 system—server 进程通讯的函数,以此作为“欺上瞒下”的目的,欺骗系统“以为”只有一个 apk 在运行,瞒过插件让其“认为”自己已经安装。

hook 点:

VAppManagerService#installPackage():

PackageSetting ps; if (existSetting != null) { ps = existSetting; } else { ps = new PackageSetting(); } ps.dependSystem = dependSystem; ps.apkPath = packageFile.getPath(); ps.libPath = libDir.getPath(); ps.packageName = pkg.packageName; ps.appId = VUserHandle.getAppId(mUidSystem.getOrCreateUid(pkg)); if (res.isUpdate) { ps.lastUpdateTime = installTime; } else { ps.firstInstallTime = installTime; ps.lastUpdateTime = installTime; for (int userId : VUserManagerService.get().getUserIds()) { boolean installed = userId == 0; ps.setUserState(userId, false/*launched*/, false/*hidden*/, installed); } } PackageParserEx#initApplicationInfoBase(): ai.enabled = true; ai.nativeLibraryDir = ps.libPath; ai.uid = ps.appId; ai.name = ComponentFixer.fixComponentClassName(ps.packageName, ai.name); ai.publicSourceDir = ps.apkPath; ai.sourceDir = ps.apkPath; VPackageManagerService#getActivityInfo(): @Override public ActivityInfo getActivityInfo(ComponentName component, int flags, int userId) { checkUserId(userId); flags = updateFlagsNought(flags); synchronized (mPackages) { VPackage p = mPackages.get(component.getPackageName()); if (p != null) { PackageSetting ps = (PackageSetting) p.mExtras; VPackage.ActivityComponent a = mActivities.mActivities.get(component); if (a != null) { ActivityInfo activityInfo = PackageParserEx.generateActivityInfo(a, flags, ps.readUserState(userId), userId); ComponentFixer.fixComponentInfo(ps, activityInfo, userId); return activityInfo; } } } return null; }

...

 

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。