多线程应用程序中注入的 mprotect 调用的切换标志
Toggling flags for injected mprotect calls in multi-threaded applications
我正在开发一个项目,其中动态库 (.so
) 在运行时注入到某个目标程序中(动态检测)。该库使用 mmap/munmap
处理自己的内存。出于安全原因,要求库中的某些映射区域 仅 可通过库中公开的 API 进行写入。
我们所做的是切换内存区域的写标志使用mprotect
和PROT_WRITE
在prologue/epilogue库函数,例如:
void foo(void) {
mprotect(addr, PAGE_SIZE, PROT_READ | PROT_WRITE);
...
...
mprotect(addr, PAGE_SIZE, PROT_READ);
}
这适用于单线程应用程序。对于多线程应用程序,如果上下文切换(到同一进程中的不同任务)发生 after,则同一进程中的其他任务可能能够写入映射的库区域PROT_WRITE
已设置(因此内存是可写的)并且 在 它被清除之前。
所以,问题是:是否可以在 foo
returns 之前禁用进程中的其他任务?如果没有,您建议如何解决这个问题?
您的安全模型无效。如果您的库代码可以 mprotect
这些区域可写,那么程序的任何其他部分也可以。你无法内省地阻止这种情况。这种安全属性只能通过某种外部监督来实现,直接由内核或通过跟踪过程(例如使用传统的 ptrace 或 seccomp 跟踪)。
如果您实际上不需要 安全性 属性,而只是想通过已经信任的代码可靠地捕获写入,您 可以通过跟踪所有线程,用 pthread_kill
向它们发出信号,并让信号处理程序阻塞直到信号线程允许它们继续,从而实现类似的目的。
我正在开发一个项目,其中动态库 (.so
) 在运行时注入到某个目标程序中(动态检测)。该库使用 mmap/munmap
处理自己的内存。出于安全原因,要求库中的某些映射区域 仅 可通过库中公开的 API 进行写入。
我们所做的是切换内存区域的写标志使用mprotect
和PROT_WRITE
在prologue/epilogue库函数,例如:
void foo(void) {
mprotect(addr, PAGE_SIZE, PROT_READ | PROT_WRITE);
...
...
mprotect(addr, PAGE_SIZE, PROT_READ);
}
这适用于单线程应用程序。对于多线程应用程序,如果上下文切换(到同一进程中的不同任务)发生 after,则同一进程中的其他任务可能能够写入映射的库区域PROT_WRITE
已设置(因此内存是可写的)并且 在 它被清除之前。
所以,问题是:是否可以在 foo
returns 之前禁用进程中的其他任务?如果没有,您建议如何解决这个问题?
您的安全模型无效。如果您的库代码可以 mprotect
这些区域可写,那么程序的任何其他部分也可以。你无法内省地阻止这种情况。这种安全属性只能通过某种外部监督来实现,直接由内核或通过跟踪过程(例如使用传统的 ptrace 或 seccomp 跟踪)。
如果您实际上不需要 安全性 属性,而只是想通过已经信任的代码可靠地捕获写入,您 可以通过跟踪所有线程,用 pthread_kill
向它们发出信号,并让信号处理程序阻塞直到信号线程允许它们继续,从而实现类似的目的。