在多线程应用程序中为注入的mprotect调用切换标志

Toggling flags for injected mprotect calls in multi-threaded applications

本文关键字:调用 mprotect 标志 注入 多线程 应用程序      更新时间:2023-10-16

我正在研究一个动态库(.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返回之前,是否有可能禁用进程中的其他任务?如果没有,你建议如何解决这个问题?

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

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