android 论坛_Android 应用多开对抗实践
目录
- Android 应用多开对抗实践
- 应用多开技术总结
- 系统级技术
- 用户级技术
- 拆招
- 反系统级应用多开
- 简单粗暴的代码
- 验证
- 可改进
- 反用户级应用多开
- 仍然是简单粗暴的代码
- 验证
- 威力加强版
- 对用户级应用多开的理解
- 业务前端白名单
- 后记
应用多开技术总结
系统级技术
多开技术方案 | 发行版 APP |
---|---|
Android 多用户功能 | OEM系统自带的"手机分身"、"应用双开",和 "Island/炼妖壶" 等各种 "Android for work" 产品 |
chroot
|
暂无发现 APP |
多用户功能
多用户模式主要用到
UserManager
相关类,切换不同的用户,在不同的用户下运行 App,实现多开。最直观的例子是 Android 手机上的多用户
功能,手机分身
功能,以及am switch-user
命令,这种简单粗暴的用法会将 Android 服务都运行一份,如果只用于应用多开,且不说资源消耗,切换用户是在麻烦。在 Android 5.0 在基于多用户功能 添加了
Android for work
功能,可以在同一个桌面启动器下使用受限用户启动 APP,不再需要切换界面。同时将权限开发给了非系统应用。chroot
UNIX 的 chroot 系统调用在 Android 上也能用,需要 root 权限。在本地挂载运行精简版系统镜像,使用远程桌面软件如 VNC 等访问本地多开的系统。尚未发现发行版 APP,可能在 ARM 服务器云手机中用到。
用户级技术
多开技术方案 | 发行版 APP |
---|---|
VirtualApp | VirtualXposed, DualSpace |
MultiDroid | LBE平行空间, Parallel Space |
DroidPlugin | 分身大师 |
Excelliance | 双开助手, MultiAccount |
其它 | 虚拟大师 |
在用户级的多开技术中,还可以在按设计用途划分出三类
- “容器”:VirtualApp、MultiDroid
- 热更新/插件化:DroidPlugin、Excelliance
- 虚拟系统:虚拟大师
具体实现原理大家可以翻论坛里的 精品贴,这里不多描述。
值得一提的是,某云手机团队的 "虚拟大师" 产品,实现在用户态运行了一个精简版的 Android 系统镜像,在系统库中拦截了几乎所有系统调用,使用类似前文提到的 chroot
挂载系统镜像的方法运行,有兴趣的同学可以看一看。
拆招
反系统级应用多开
仅多用户方案的多开,忽略
chroot
/lxc
简单粗暴的代码
// --- C++ --- #include <unistd.h> bool isDualApp(){return 0 != getuid()/100000;}
1 2 3 |
|
一行代码完事了?
完事了,真的完事了。
但是为什么?
Android 系统中,如果开启了多用户模式,会存在一个主用户和若干受限用户。
把 MIUI 的 "手机分身" 和 "应用双开" 功能都打开,可以看到有三用户,0、11 和 999,分别对应主用户、"手机分身" 和 "应用双开"
1
2
3
4
5
6
7
8
# --- adb shell ---
$ ls
-
al
/
data
/
user
/
total
52
drwx
-
-
x
-
-
x
4
system system
4096
2019
-
09
-
05
11
:
49
.
drwxrwx
-
-
x
42
system system
4096
2019
-
04
-
22
20
:
32
..
lrwxrwxrwx
1
root root
10
1970
-
08
-
23
18
:
57
0
-
>
/
data
/
data
drwxrwx
-
-
x
221
system system
16384
2019
-
09
-
05
11
:
50
11
drwxrwx
-
-
x
13
system system
16384
2019
-
09
-
12
17
:
53
999
使用多用户模式实现的多开,在客户端中可以通过 Android SDK 的 UserManger
类判断当前运行 APP 的用户是否为主用户和受限用户
1 2 3 4 5 6 7 8 9 |
|
顺着线索,找到 UserHandler
类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
|
可看到通过 uid/100000 获得 Android 的 UserId,同时通过其它 final 字段和相关注释得知 OWNER/SYSTEM/ADMIN
的 UserId 是 0,因此我们可以通过 uid/100000 为 0 判断为主用户,非主用户直接判为多开即可。
验证
使用上文提到的 MIUI 中的 "应用双开" 功能,在进程中找到 UserId 999 运行的进程,因为第一列显示成了用户名,进 /proc/${PID}/status
查看进程 uid。uid / 100000 是 999,没毛病。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
|
可改进
- 区分各种系统级双开/分身模式
反用户级应用多开
仍然是简单粗暴的代码
测试代码一
// --- C++ --- #include <unistd.h> #include <sys/stat.h> #include <string> bool isDualApp(std::string dataDir) {return 0 == access((dataDir + "/../").c_str(), R_OK); }
测试代码二
1 2 3 4 5 |
|
dataDir 目录的父级目录理论上归属 system
用户或 root
用户,除非是系统应用,否则不能访问。
补充
为什么使用 dataDir 而不是 nativeLibraryDir 或 sourceDir 呢?
看 nativeLibraryDir 和 sourceDir 目录所在的位置,base.apk 权限
rw-r-r--r--
任意用户读取,lib 目录权限rwxr-xr-x
任意用户读取和执行
1
2
3
4
5
6
# ls -al /data/app/com.example.checksandbox-ElZnrZIb5m2rbBv_3K8nZQ\=\=/
total
2420
drwxr
-
xr
-
x
3
system system
4096
2019
-
09
-
24
16
:
15
.
drwxrwx
-
-
x
80
system system
12288
2019
-
09
-
24
16
:
15
..
-
rw
-
r
-
-
r
-
-
1
system system
2440234
2019
-
09
-
24
16
:
15
base.apk
drwxr
-
xr
-
x
3
system system
4096
2019
-
09
-
24
16
:
15
lib
而 dataDir 的目录权限
rwx------
,私有不公开
1
2
3
4
5
6
7
# ls -al /data/user/0/com.example.checksandbox/
total
40
drwx
-
-
-
-
-
-
5
u0_a366 u0_a366
4096
2019
-
09
-
24
16
:
15
.
drwxrwx
-
-
x
271
system system
20480
2019
-
09
-
24
16
:
15
..
drwxrws
-
-
x
2
u0_a366 u0_a366_cache
4096
2019
-
09
-
24
16
:
15
cache
drwxrws
-
-
x
2
u0_a366 u0_a366_cache
4096
2019
-
09
-
24
16
:
15
code_cache
drwxrwxr
-
x
5
u0_a366 u0_a366
4096
2019
-
09
-
24
16
:
15
lldb
因此,对于用户级多开软件来说,仅是实现多开功能,完全可以复用原本的 base.apk 和 lib,不需要在自己目录中释放一份,而 dataDir 目录却是必须要另外准备的。
验证
代码放 APP 里跑一遍看看
测试代码一结果
技术 | 发行产品 | 结果 |
---|---|---|
DroidPlugin | 分身大师 | 阴性 |
VirtualApp | VirtualXposed | 阳性 + |
VirtualApp | DualSpace | 阳性 + |
MultiDroid | LBE平行空间 | 阳性 + |
Excelliance | 双开助手 | 阳性 + |
其它 | 虚拟大师 | 阳性 + |
emmm,看来三六零在文件系统上的功能做得挺完善的,access
访问 dataDir 的父目录时返回了 -1 (errno: 13 Permission denied),其它的没什么问题
测试代码二结果
技术 | 发行产品 | 结果 |
---|---|---|
DroidPlugin | 分身大师 | 阳性 + |
VirtualApp | VirtualXposed | 阳性 + |
VirtualApp | DualSpace | 阳性 + |
MultiDroid | LBE平行空间 | 阳性 + |
Excelliance | 双开助手 | 阳性 + |
其它 | 虚拟大师 | 阳性 + |
到底还是我高估了三六零。。。
威力加强版
上面给的两份代码容易被绕过,稍微换个姿势,获取到真实的路径,再利用父级目录进行检测。
1 2 3 |
|
由于睡懵了忘记了细节,这里用 Java 写了份 "伪" 代码,由于没能绕过 hook,多少会存在瑕疵,但是原本的 ASM 代码绕过各种 Hook,达到通杀
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 |
|
对用户级应用多开的理解
两个关键技术点:Binder IPC 拦截 、系统函数拦截
两个直观特征:沙盒破损、共享 UID
Binder IPC 拦截用于重定向 APP 与 Android 系统服务、其它应用的远程调用;
系统函数拦截主要用于重定向 I/O 操作,如果搞定所有 libc 函数,再配合修改过的 linker ,可以在一定程度上仿真 Linux 系统;
在用户级的多开中,没有系统的支持,缺少沙盒机制,应用的数据目录一般内嵌在宿主的数据目录中。同时,在同一个用户级多开软件中,内部的 APP 共享宿主的 UID,意味着他们都具有相同的权限,在系统层面上可以相互访问。因此,围绕这点,除了上文给出的方法外,还有三百六十五天不重复的姿势能够检出用户级的多开。
- 由于是在用户态实现的隔离,不建议用于政企办公保密场景,有此类需求的可以直接用系统自带的 "Android for work" 功能。
业务前端白名单
如果己方有用户级的多开辅助工具,需要在 前端 检测上添加白名单,通常有三种白名单:
- APK 包名
- APK 签名公钥
- APK 内文件(文件名/CRC/HASH)
前端白名单会成为一个很好的攻击点,需要相关业务的后端一起配合来弥补
android 论坛_Android 应用多开对抗实践相关推荐
- 微信小游戏直播在Android端的跨进程渲染推流实践
本文由微信开发团队工程师"virwu"分享. 1.引言 近期,微信小游戏支持了视频号一键开播,将微信升级到最新版本,打开腾讯系小游戏(如跳一跳.欢乐斗地主等),在右上角菜单就可以看 ...
- Android开发_android界面效果全汇总
(一)Activity页面切换的效果 先介绍下左右滑动切换Activity,对于复杂的手势原理一样,具体后述. 主要原理为监控触屏事件和手势事件,在触屏事件处理函数中调用手势事件处理函数,表示用户触屏 ...
- JavaScript|拖拽|仿Android手机九点连线开锁
最简单的JavaScript拖动代码 <script> var xx=0,yy=0; function a(v) { xx=event.x-v.offsetLeft; yy=event.y ...
- android studio有时打不开,android studio 打不开的几种可能
前几天碰到了内存不足报错的提示 也没看别的 直接点击了 关闭 在之后也没管 忙别的事情了 在然后打开Android studio 没反应怎么也打不开了 上网查了下 有一下几种可能 便是了. 1 .又说 ...
- 国内8大热门android论坛
国内8大热门android论坛 Jul 16 Posted by APP虎 in android入门, android论坛 国内8大热门android论坛 android论坛随着andriod系统的发 ...
- Android Library上传到JCenter仓库实践
前言 这段时间研究了下以前做app开发的时候并没有太过关注的JCenter仓库,在实际开发当中通常都是使用第三方开发者上传到jcenter的library,而我们使用的这些library或者plugi ...
- 在Android上使用libgdx-box2d物理引擎的实践-20220113
根据文章"在Android上使用libgdx-box2d物理引擎"后实践过程 1. gralde报错解决,猜测是gralde语法和版本号问题. 1.去maven库手动下载com.b ...
- android 弹出框崩溃_Android处理崩溃的一些实践
对于任何程序来说,崩溃都是一件很难避免的事情,当然Android程序也不例外.在Android程序中,引起崩溃的多属于运行时异常或者错误,对于这些异常我们很难做到类似Checked Exception ...
- android 仿微博评论编辑框_android 仿新浪微博开写篇
准备,分析: 分析下这个界面,主要由几个tabbar分管不同的界面,首先我们会想到TabActivity,这是我们以前的做法,安卓更新越来越好,功能也越来越完善,我们也要时刻更新自己的技术,要不就会被 ...
- android 修改编译内核源码 对抗反调试
0×00 写在前面 攻防对立.程序调试与反调试之间的对抗是一个永恒的主题.在安卓逆向工程实践中,通过修改和编译安卓内核源码来对抗反调试是一种常见的方法.但网上关于此类的资料比较少,且都是基于AOSP ...
最新文章
- linux su和sudo命令的区别(转)
- 白光驱动器替代指南(转)
- 【Python学习系列二十五】数据结构-有向图绘制
- 小游戏编程代码复制_少儿编程是不是来玩游戏?这个到底要学多久?
- 【2.0】SpringBoot连接MySql 8.0的url设置
- 项目经历怎么写_这样写项目经历可以锦上添花
- access查询设计sol视图_Access删除索引
- ToStringBuilder.reflectionToString
- 【Unity3D插件】DoTween插件(三)
- 2021数学建模国赛b题思路总结
- 给初学日语者的几点建议——词汇篇
- 机器学习十大算法实现python代码汇总
- 三年级计算机 键盘指法 教案,第13课 键盘指法练习
- 分享台阶价格对比逻辑。(商城中购买数量越多,单价越低)
- 「NOI2018」冒泡排序
- 硅基压力传感器—MEMS
- 教你如何全面认识磁盘阵列柜
- 免费英文写作批改网站
- C语言中typeof作用,c语言中typeof关键字
- 中文为什么没有词干提取_词干中没有小写字母
热门文章
- 计算机软件如何助力科研,研究生必备科研绘图软件,助力科学研究
- #151 – Dependency Properties Remember Non-Coerced Values(依赖属性强制转换之前的值会被记住)
- gclient多源码管理工具 DEPS文件
- (Research)肝肿瘤免疫微环境亚型和中性粒细胞异质性
- 【项目实战】——历史数据归档
- Docker容器设置自动启动的方法
- 固态硬盘量产工具_FORESEE G500发布,江波龙国产固态硬盘再发声
- PPT参考线_Alt+F9
- Windows 7 64位 旗舰版 激活 心得 提示:系统保留分区设置驱动器号
- 【word】右上角标