MachO如何强制验证代码签名

  为了使代码签名证书正确配置并且代码签名真正有效,非常重要的一步就是要保证验证过程顺利执行,没有遗漏。当前签名验证是发生在内核模式下,而非用户模式下。签名的验证发生在两个阶段:加载可执行文件时、实际访问二进制代码时(Page Fault)。分成两个阶段也是出于性能方面的考虑,因为二进制文件是动态加载的,对于还没加载的部分仅当其加载如内存时,也即发生 Page Fault 时再进行签名验证。

  

  1、可执行文件的加载

  

  可执行文件的加载出现在execve()/mac_execve()或posix_spawn()系统调用被触发的时候。对于MachO,exec_mach_imgact()会被调用,在解析文件时它会找到LC_CODE_SIGNATURE的位置。代码签名二进制块会被加载到内核的统一高速缓存缓冲区中。

  

  2、Page Fault时的处理

  

  可以查看 osfmk/vm/vm_fault.c[5] 的代码

  

  /*

  

  * CODE SIGNING:

  

  * When soft faulting a page, we have to validate the page if:

  

  * 1. the page is being mapped in user space

  

  * 2. the page hasn't already been found to be "tainted"

  

  * 3. the page belongs to a code-signed object

  

  * 4. the page has not been validated yet or has been mapped for write.

  

  */

  

  #define VM_FAULT_NEED_CS_VALIDATION(pmap, page, page_obj)  \

  

  ((pmap) != kernel_pmap /*1*/ &&     \

  

  !(page)->cs_tainted /*2*/ &&     \

  

  (page_obj)->code_signed /*3*/ &&     \

  

  (!(page)->cs_validated || (page)->wpmapped /*4*/))

  

  当 Page Fault 满足以上条件时将触发签名验证过程:

  

  1、该页面正在用户空间中映射

  

  2、这个页面还没有被发现为 tainted

  

  3、该页属于一个代码签名对象

  

  4、页面还没有被验证,或者还没有被映射为可写状态


请使用浏览器的分享功能分享到微信等