[空想] 改造 FreeBSD 变成移动设备操作系统

2017-08-05 17:56:58 +08:00
 noli
目的:兼有开放性,以及安全性。

FreeBSD 也是一个重要的开源操作系统。
FreeBSD 的 Jail 本身就是一个非常好的操作系统级别的安全基础。

拿 FreeBSD 改造成一个开放型的 另一个 iOS,
搭配 C/C++ Rust Swift ObjC Golang 等等的可生成原生二进制应用的 App

会不会有前景呢
11209 次点击
所在节点    奇思妙想
75 条回复
hjc4869
2017-08-09 17:07:28 +08:00
@noli 你不理解 ObjC 和水果那一套东西。编译出来全是动态调用。
举个例子
[[NSString alloc] init];
翻译成 C 代码就是
void* cls = objc_getClass("NSString");
void* obj = objc_msgSend(cls, NSSelectorFromString(CFSTR("alloc")));
obj = objc_msgSend(obj, NSSelectorFromString(CFSTR("init")));
hjc4869
2017-08-09 17:15:16 +08:00
JSPatch 并没有调用私有 API,只是用了上面我说的这几个函数去实现了任意 API 调用
zhicheng
2017-08-09 17:20:10 +08:00
@noli 既然在 “讨论” BSD 和 Linux,就不要把 Windows 扯进来,不能我跟你讨论 BSD 和 Linux 的时候你突然来了句 Linux 不如 Windows。这个不是讨论的内容。或者用你的观点,把 Linux 换成 FreeBSD 也成立,更可怕的是 Linux 桌面现在已经比较稳定了,FreeBSD 呢?

不是 Linux 是万能的,而是工程师是万能的,而 Linux 充当了中间的桥梁,它对于很多项目是一个定制化非常高的框架。

iOS 不是 FreeBSD,真的不是。从单纯的 syscall 的角度,FreeBSD 和 Linux 是完全一样的产品,谁都没有优越感。或者 Linux 更好一些,因为更容易定制。

我根本就不知道你说的“安全 API ”是个什么鬼东西。

Linux 就是给别人一种多样性让大家自己开发或者选择,而不是官方定调你只能用这个,比起那些老牌或者正统 UNIX,Linux 更像是集市,谁的东西好,谁就卖的好。

我并不知道 YunOS 是基于 FreeBSD 也没有搜到任何证据。不过还是感谢你没提 Kylin。你不用复述一遍关于 GPL 以及大企业的言论,事实是大企业非常讨厌 GPL,但是 Linux 深得民心他们也没有办法。

你还是别加私货了,OpenSolaris 在当时不可能活下来,现在也不可能活下来,未来也不可能活下来。很多人相信 Solaris 神话,但其实 Solaris 是一个更新慢,运行慢,漏洞多,不开放的系统。它有很多很先进的功能,但最后还是没活下来,OpenSolaris 想披一套 GNU 的皮复活,但一个没有经过市场验证又是由一家公司把持的项目,大家并不买账。

重复一下 bottom line: FreeBSD 是一个很好的 OS,Linux 也是一个很好的 OS。他们两个是替代品,各有各的市场和策略,任何一个都不比另一个好。不要用 FreeBSD 就是比 Linux 好,用 FreeBSD 就是对,Linux 就是错这种 “清真主义” 来评价技术。
hjc4869
2017-08-09 17:31:04 +08:00
另外水果对 JSPatch 的处理方法简直就是在搞笑,“扫描字符串”直接拒绝审核
noli
2017-08-09 17:36:56 +08:00
@hjc4869

void* cls = objc_getClass("NSString");
void* obj = objc_msgSend(cls, NSSelectorFromString(CFSTR("alloc")));
obj = objc_msgSend(obj, NSSelectorFromString(CFSTR("init")));

你说的这些明明就是平铺直白的 C 函数静态调用。当然对于某种语言来说它可能是什么动态调用,但在 loader 看来,这些函数的入口在编译后就是明确的、固定的,所以就是 静态调用。

我说的是在运行时 生成一个函数,并把这个函数的入口地址放入某个寄存器后跳转执行。

跟 JSPatch 有没有直接调用私有 API 没有关系,有关系的是可以在生成的函数里面去调用私有 API。

https://jspatch.com/Docs/appleFAQ
noli
2017-08-09 17:39:50 +08:00
@hjc4869

无论你怎么理解 Apple 的审核行为,你对注入二进制代码的动态调用理解是错误的。
iOS 并不拒绝动态执行 script 代码,拒绝的是动态执行任意二进制代码。
hjc4869
2017-08-09 17:41:16 +08:00
@noli 问题是被调用的是 NSString.alloc NSString.init,这些是作为变量被送入,objc_xxx 调用的是什么跟输入的变量有关,这就叫做 dynamic dispatch。
意思就是只要脚本可以调用 objc_xxx 这些函数,就能调用包括 NSString 在内的一切 objc native api。后者都是动态的,静态检查不出来。
hjc4869
2017-08-09 17:49:44 +08:00
@noli
除了 JSPatch,甚至还有人做了把 objc 编译成字节码,然后解释运行。
动态调用根本不需要 JIT,有一个解释器就行。
类似的技术还有 Microsoft COM,纯 native,但是就是可以用解释器动态调用( IDispatch )。

另外,你能不能不要随便说别人的理解是错误的?你看看上面从我说打住封闭 /开放的话题开始,我纠正了你多少技术方面错误的认知?如果我是王垠,上面每个回复都是建议零售价 30 元的。
noli
2017-08-09 17:49:44 +08:00
@zhicheng

你怎么定义 “ linux 桌面比较稳定” 我不管,你认为 linux 怎么先进我不管,
你告诉我哪个版本的 Linux kernel 有 类似 FreeBSD jail 的 设施,
你告诉我哪个版本的 Linux 可以支持判断某个 bin 是某个开发者开发的。

要不是 linux 最近终于想起 跟进 DTrace,我还想问问你 linux 什么时候打算支持这个。

当我说前瞻性的时候你跟我说实现,当我说实现的时候你跟我说可能性。


你不想或者不能好好讨论就闭嘴吧,感谢你的铜币了。
noli
2017-08-09 17:59:15 +08:00
@hjc4869

什么时候 objc 编译成中间字节码是新鲜事了,LLVM IR 不就是干这个的吗,clang 不就是搞这些的吗?
objc 的几乎每个调用都会编译成 objc_msgSend 这是常识吧?

如果你知道 objc_msgSend 是怎么实现的,你就明白为什么这些都是静态调用了,
以及为什么你说的我说的 二进制代码 注入是两回事。

objc_msgSend 传入一个字符串进去,要调用的函数的入口就已经确定了,
这些函数都是 objc runtime 动态链接到当前进程的时候就已经设置好入口地址了,可以调用任意函数确实是和 JIT 无关,而且 Apple 也可以检查得出来。

然而这些都不是 JSPatch 被禁的原因。
noli
2017-08-09 18:02:01 +08:00
@hjc4869

“纠正了你多少技术方面错误的认知”。
无知真是可怕。

显然我和你之间要么误会深得无法解开,要么就是其中一个是无知而不自知。
算了。结帖了。已经离题万丈了。
hjc4869
2017-08-09 18:03:27 +08:00
@noli 你 objc_msgSend 输入一个字符串*变量*,编译时谁知道你要调用啥?
VmuTargh
2017-08-09 18:15:24 +08:00
第一次听到斗地主还可以三个人都赢牌的套路
noli
2017-08-09 18:38:17 +08:00
@hjc4869 呐,我帮你提高姿势水平,这次 30 块就当免费体验优惠了。

三种情况:

1. 字符串变量编译时可以确定,也就是说直接存储在数据段,所以这个时候肯定可以查到要调用哪个函数
从 objc 源码编译得到的 bin 调用都大多数是这种类型,因为要 send 的 msg 在编译时确定,这里包括所谓的 dynamic dispatch,其实只不过是用字符串作为 key 取代 C++ vtable (用 index 作为 key )

2. 字符串变量编译时不确定,但肯定是某个 objc 的函数, 这时候可以通过一遍模拟加载知道所有 在 objc runtime 中注册的类,如果在进入 main 之前没有被加载,那么进入 main 之后也不会被使用。这一步的检测普通开发者不一定做得到,但是 loade 人完整实现得 Apple 肯定可以做得到。

这里 jspatch 已经有越界的风险了,因为 可以用自定的 函数入口 来改掉 iOS SDK 原本函数的入口。

更进一步,可以猜测 私有 API 的入口地址做跳转。当然我不确定 JSPatch 有没有这么做,据我所知 iOS 好像没有随机更改 dll 中的入口函数地址以避免被猜测的功能( Windows 上肯定有,作为一种安全防范),所以即使 JSPatch 没有这么做,其他人完全可以通过 JSCore 来做到这种效果,JSPatch 也控制不了。

所以,如果 JSPatch 只是老老实实地把 JS 代码翻译成 objc_msgSend 是肯定不会被禁的,这已经足够实现所谓的 热更新了。

如果改掉 iOS SDK 调用入口,甚至尝试通过猜测入口来调用私有 API 的话,就肯定会被禁。

事实上,甚至可以通过混淆字符串,来调用 私有 API,原理你知道的,只要在真正调用 objc_msgSend 之前生成原本要调用的私有 API 字符串,就可以实现了。
noli
2017-08-09 19:05:59 +08:00
@VmuTargh 说明按照斗地主的模型来梳理三者关系可能不太对。

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

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

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

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

© 2021 V2EX