回头再看,感觉 android 对所有 app 开放 NDK 是大败笔

2018-07-10 18:57:31 +08:00
 s82kd92l
开放 NDK 初衷应该是为了应对很少场景下的高性能要求,比如直接处理音频 /视频编码。而随着 Java vm 优化越来越好,NDK 作为高性能替代品的作用也越来越小了。最需要性能的游戏其实也可能绕过 NDK,用 java+shader+renderscript/opencl/vulkan 做到不错的效果。

相反,NDK 的大门一开,却使得无数不务正业的黑科技成为可能:各种 hook/hotpatch 修改 Java VM 本身,各种 native 层的进程保活,长连接保活,访问私有 API,甚至利用 linux 内核漏洞 root。现在稍微大一点的项目,不再 native 层做反 hook 加壳都不好意思跟人打招呼,而且 hook 这些本来就是猫捉老鼠的游戏,甚至可以说是军备竞赛,战场是在用户的手机上,武器就是双方程序员的时间和精力,受伤的是 cpu 和电池。Google 这么多年在 android 安全上的投入,包括 selinux,seccomp 也都是主要针对来自第三方 NDK 代码的威胁。

所以我觉得 NDK 应该做成高危权限,没有明确的理由禁止使用,这样 android 的生态会清净得多。
16064 次点击
所在节点    Android
60 条回复
cxl008
2018-07-11 13:44:45 +08:00
@nicevar 正解
VYSE
2018-07-11 14:36:45 +08:00
@s82kd92l #36 Runtime.getRuntime().exec()
and ptrace is a syscall
s82kd92l
2018-07-11 16:23:26 +08:00
@VYSE 你可能对 exec()和 syscall 有误解...

exec()是执行命令行程序。syscall 是指 open/fork/ioctl 这种.这年头就算是 NDK 程序也没有随便用 syscall 的本事,会被 seccomp 挡住。
VYSE
2018-07-11 16:33:13 +08:00
@s82kd92l #43 你可能有误解, 我说 exec 是说不需要 NDK, ELF 始终是可以执行的, 甚至可以用 Linux arm toolchain 静态编译出不依赖 Android linker 的 ELF.

第二 ptrace 的确是 syscall, 见 bionic 代码
unsigned int __fastcall _ptrace(enum __ptrace_request a1, void *a2, void *a3)
{
unsigned int result; // r0

result = linux_eabi_syscall(__NR_ptrace, a1, a2, a3);
if ( result > 0xFFFFF000 )
result = j___set_errno_internal(-result);
return result;
}

第三 ptrace 自己进程来做 code modify 从来没有被 seccomp 封过, 见市面多数加壳方案.
s82kd92l
2018-07-11 18:12:46 +08:00
@VYSE ptrace 自己进程和 ptrace 其他进程两码事,普通 linux 发行版都有 yama 防止随便 attach 其他进程,何况 android 这种久经考验的
VYSE
2018-07-11 18:21:29 +08:00
@s82kd92l #45 我原话"ptrace hook 上去也可以实现 JNI 提供的功能", 你怎么非要脑洞到 ptrace 其他 UID 的进程, 我是说通过 ptrace 可以实现很多 JNI 调用, 比如 VirtualApp 里用到的 Substrate.
s82kd92l
2018-07-11 18:28:39 +08:00
@VYSE 不是限制 ptrace 其他 UID,而是其他 PID
VYSE
2018-07-11 18:30:39 +08:00
@s82kd92l #47 .......你自己再查查试试
youxiachai
2018-07-11 18:31:32 +08:00
我感觉...早期.android 不开放 NDK..早就 GG 了...毕竟远古时代...手机硬件性能那么差

说败笔..其实,你说的缺点,其实大部分都不是事...起码对于一个生态来说...

不能因为有黑暗的存在..就不能用光明的手段啊...

lz 显然陷入一种因咽废食的状态..
s82kd92l
2018-07-11 23:45:01 +08:00
@VYSE 嗯,你是对的。我在 termux 里能够对其他 pid 做 strace, 看来目前 Android 是允许同一个 uid 下的进程相互调试的
tempdban
2018-07-12 00:49:39 +08:00
你还是不明白啊,谷歌要是想做,他有一百万种方法限制你,你附言里提到的方法已经是很麻烦的办法了。
国产手机系统就限制的不错,方案也成熟,谷歌拿去直接用呗。
他为啥不做?就是不想得罪开发者。
还有兄弟,等到你要实现一个需求,但是因为系统限制实在无法实现的时候,你就知道愁了,让马儿跑又不让马儿吃草的例子多了去了,用户才不管怎么解释,他就是要,WP 就是活生生的例子,多少 WP 软件作者被喷到不行,更新纪录里写着爱用不用。
hook/hotpatch 修改 Java VM 那也只是改了我这个进程的内存页,别的进程影响不到啊。
各种 native 层的进程保活,长连接保活,访问私有 API。
兄弟你 ps 都能看出来的东西,系统真的看不出来么,API 不存在私有不私有兄弟。能用隐藏的 API 那是本事,API 没用做他干嘛。
别用户的思维来搞产品,懂得 app 背后机制的人还是少数。
有很多事是我们不得不妥协的
tempdban
2018-07-12 01:02:11 +08:00
还有兄弟,你正文中每个英文单词,都是要仔细打磨你才能明确的知道他究竟在干些什么。
tempdban
2018-07-12 01:13:24 +08:00
@VYSE 正想抽空看一眼 VirtualApp 到底是怎么一个黑科技,原来还是 ptrace 啊,感谢送上。
另外请教一下 android 的 linker 和平时用的 gold 有啥区别,不都是读 ELF 吗?
VYSE
2018-07-12 03:13:19 +08:00
@tempdban #53 linker 本质是负责加载 so, 最初两者只是实现细节上的区别, 比如之前研究一般情况可以替换:
https://v-e-o.blogspot.com/2017/12/run-arm-executables-on-linux-x86-with.html

不过最新的 Android linker 已经加入 PIE only, namespace, ZIP LD_LIBRARY_PATH 等一堆 feature, 现在已经没法直接移植到 Linux 平台
我司也有产品直接在 LXC 里跑 Android, 两套 linker 随便用
VYSE
2018-07-12 03:55:03 +08:00
@tempdban #53 搞错了一点 VirtualApp 并没有用 ptrace 把 substrate so inject 进去, 而是自己代码直接 load library 的. Frida, ADBI 这种会用 ptrace.
qsjh898
2018-07-12 11:06:35 +08:00
要是没有 NDK,你还用个鸡毛微信
codehz
2018-07-13 12:47:54 +08:00
@VYSE #54 用 hybris 这个库还是可以加载 android 上的 so 文件的,不过由于自己实现了链接的逻辑,所以 gdb 调试就没法用了
VYSE
2018-07-13 14:53:15 +08:00
@codehz #57 这个库不错, 做了不少 compat 补丁, 不过要是能封装一整套做 glue 的 libc, linker 直接跑已编译好的 ELF 就更好了
tempdban
2018-07-27 01:54:00 +08:00
@VYSE 我其实对这类黑科技很感兴趣,纯靠自己研究太慢了,请问可否留个联系方式,以后讨教
VYSE
2018-07-27 10:27:43 +08:00
@tempdban twitter @VYSEa

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/469685

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX