【问题标题】:Toggling flags for injected mprotect calls in multi-threaded applications在多线程应用程序中切换注入 mprotect 调用的标志
【发布时间】:2015-10-26 07:32:40
【问题描述】:

我正在开发一个项目,其中在运行时将动态库 (.so) 注入到某个目标程序中(动态检测)。该库使用mmap/munmap 处理自己的内存。出于安全原因,要求库中的某些映射区域可通过库中公开的 API 写入。

我们所做的是在库函数的序言/结尾处使用mprotectPROT_WRITE 切换 内存区域的写入标志,例如:

void foo(void) {
  mprotect(addr, PAGE_SIZE, PROT_READ | PROT_WRITE);
  ...
  ...
  mprotect(addr, PAGE_SIZE, PROT_READ);
}

这适用于单线程应用程序。对于多线程应用程序,如果在PROT_WRITE 之后发生上下文切换(到同一进程中的不同任务),同一进程中的其他任务可能能够写入映射的库区域已设置(因此内存是可写的)并且它被清除之前。

所以,问题是:在foo 返回之前,是否可以禁用进程中的其他任务?如果没有,您建议如何解决这个问题?

【问题讨论】:

  • 查看锁、信号量、条件变量 :)
  • @TheBroessor 只有当您可以明确识别需要排除的代码时,这些才有效。当那是“除此代码之外的所有内容”时将不起作用。
  • 取决于你如何定义临界区,你可以实现,对吧?更多关于抢占的信息:en.wikipedia.org/wiki/Preemption_(computing)
  • 您希望您的库将受保护的内容放入一个单独的进程中。这是唯一有意义的方法。
  • 谢谢@DavidSchwartz。这可能真的是唯一可行的解​​决方案。我们希望有一种方法可以避免使用跟踪器进程,因为这会增加很多开销,例如,由于上下文切换。

标签: c++ c linux multithreading mprotect


【解决方案1】:

您的安全模型无效。如果您的库代码可以mprotect 这些区域可写,那么程序的任何其他部分也可以。你不能内省地阻止这种情况。这种安全属性只能通过某种外部监督来实现,要么直接由内核或通过跟踪进程(例如,使用传统的 ptrace 或 seccomp 跟踪)。

如果您实际上并不需要 security 属性,而只是想要可靠地捕获已经受信任的代码的写入,您可以通过跟踪你所有的线程,用pthread_kill向它们发出信号,并让信号处理程序阻塞,直到信号线程允许它们继续。

【讨论】:

  • 我们的威胁模型假设代码执行是不可能的(在其他防御层处理),但数据损坏是可能的。我们知道,如果攻击者可以控制指向恰好在某些mprotect 调用中使用的库区域的指针,则可以更改保护标志。
  • 一个后续问题:一些编译器试图通过在只读区域中放置敏感结构(例如,虚拟表)来“强化”二进制文件。这样的解决方案不会受到同样的威胁,即劫持传递给某些mprotect 的指针吗?
  • @John:这种强化不能防止恶意代码(例如dlopening 一个不受信任的库)。它只是降低了可利用的错误转化为任意代码执行机会的风险,在这种情况下,您通常在已经实现代码执行之前没有机会影响mprotect
猜你喜欢
  • 1970-01-01
  • 2017-09-29
  • 2017-12-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-09-18
  • 1970-01-01
  • 2023-03-03
相关资源
最近更新 更多