【问题标题】:Using mprotect to make text segment writable on macOS使用 mprotect 使文本段在 macOS 上可写
【发布时间】:2020-06-24 13:07:41
【问题描述】:

这基本上就是我想要做的,

#include <sys/mman.h>

int zero() {
    return 0;
}

int main(int argc, const char *argv[]) {
    return mprotect((void *) &zero, 4096, PROT_READ | PROT_WRITE);
}

所以我试图让代码本质上是可写的。这在当前的 macOS(Catalina 10.15.2)上不起作用,它只返回 -1 并将 errno 设置为 EACCES,据我所知,这是因为缺乏权利/代码签名。我找到了我需要设置的权利,但我不知道如何去做,也不知道如何实际签署它..

如果我运行codesign -d --entitlements :- &lt;path_to_app&gt;,它会以code object is not signed at all 失败,即使我已经尝试配置登录 Xcode 一段时间(我有证书等等)。那么我该怎么做呢?实际上用 Xcode 签名并不明显,所以我相当无能。

【问题讨论】:

  • 是MacOS Catalina中PROT_WRITE的问题。我们无法通过传递权利中的所有标志来修复它。
  • 我们已经测试了所有权利的协同设计,例如com.apple.security.cs.allow-jitcom.apple.security.cs.allow-unsigned-executable-memorycom.apple.security.cs.disable-executable-page-protection,但它不起作用。这可能是 MacOS Catalina 的问题,Apple 的 hop 开发人员可以解决它。

标签: xcode macos text code-signing-entitlements mprotect


【解决方案1】:

这不是一个确定的答案,但它是一种解决方法。

您的问题是由 macOS Catalina 中的链接器 (ld64) 更改引起的。 Mach-O 标头中__TEXT 段的max_prot 属性的默认值已更改。

以前max_prot 默认值为0x7 (PROT_READ | PROT_WRITE | PROT_EXEC)。
默认值现已更改为0x5 (PROT_READ | PROT_EXEC)。

这意味着mprotect 不能使位于__TEXT 内的任何区域可写。

理论上,这应该通过提供链接器标志-segprot __TEXT rwx rx 来解决,但事实并非如此。从 Catalina 开始,max_prot 字段被忽略。而是将max_prot 设置为init_prot 的值(请参阅here)。

最重要的是,由于 macOS 拒绝执行具有可写 __TEXT(init_prot) 属性的文件,init_prot 不能设置为 rwx

一种粗略的解决方法是在链接后手动修改并将__TEXT(max_prot) 设置为0x7

printf '\x07' | dd of=<executable> bs=1 seek=160 count=1 conv=notrunc

由于代码 sn-p 依赖于被硬编码为 0xA0__TEXT(max_prot) 偏移量,因此我为 ld 创建了一个 drop-in replacement/wrapper,它尊重 max_prot 参数 segprot .

【讨论】:

  • 您可以绕过 Catalina dyld: malformed mach-o image: __TEXT segment maps start of file but is writable 使用我在此处显示的解决方法 stackoverflow.com/a/60505259/5329717 进行检查
  • 这是一个有趣的花絮!对于mprotect,我会说最好更改max_prot 属性,但很高兴知道还有其他选择。
  • 谢谢,它适用于带有此命令的子挂钩程序github.com/Zeex/subhook/issues/45
猜你喜欢
  • 1970-01-01
  • 2015-02-19
  • 1970-01-01
  • 1970-01-01
  • 2019-12-31
  • 2019-06-13
  • 2022-06-21
  • 2020-09-13
  • 2021-05-02
相关资源
最近更新 更多