@
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 字符串,就可以实现了。