Android Linux中的截获文件打开事件
假设我们有一个进程可能Android Linux中的截获文件打开事件,android,linux,unix,posix,inotify,Android,Linux,Unix,Posix,Inotify,假设我们有一个进程可能dlopen()某个第三方库。此库可以对用户只有写入权限的某些文件执行open(“仅写入日志文件”,O\u WRONLY)。如果此库试图打开文件,我们需要能够收到通知,因此稍后我们可能会dup()返回描述符并重定向输出。 很少有限制使拦截更困难: LD\u预加载被禁止-无法钩住open() inotify(7)没有帮助,因为用户对“只写日志文件”没有读取权限,并且该文件归管理员所有 我们无法访问图书馆资源,因此无法对其进行修改 “只写日志文件”在库中是硬编码的,因此我们无
dlopen()
某个第三方库。此库可以对用户只有写入权限的某些文件执行open(“仅写入日志文件”,O\u WRONLY)
。如果此库试图打开文件,我们需要能够收到通知,因此稍后我们可能会dup()
返回描述符并重定向输出。
很少有限制使拦截更困难:
LD\u预加载被禁止-无法钩住
open()
没有帮助,因为用户对inotify(7)
没有读取权限,并且该文件归管理员所有“只写日志文件”
- 我们无法访问图书馆资源,因此无法对其进行修改
在库中是硬编码的,因此我们无法传递其他名称来执行重定向“只写日志文件”
打开()
杂项文件这一事实
另外,为了避免混淆和更好地理解,它是一个带有加载JVM的常规Android应用程序。如果应用程序挂起(即所谓的ANR)-系统将向其发送SIGQUIT
。信号通过专用线程接收,该线程open()
s/data/anr/traces.txt
并向其写入JVM状态。这些数据对于调试非常有用。但由于安全原因,应用程序无法直接读取该文件(所有应用程序都会写入该文件,所以可能存在一些敏感问题)。无论如何,我相信截取我的流程将写入的内容是绝对公平的
注意:在最坏的情况下,可以找到JVM库映像(
libart.so
),并手动为open()
修补跳转槽。但是听起来不太好。如果这只是将写入(和读取)重定向到单个文件,您可以在装载命名空间中运行应用程序,并为该特定文件提供合适的绑定装载。以这种方式设置可能需要一个小的SUID二进制文件
一个更通用的解决方案很快就可以使用联合文件系统,而且要正确使用它是相当困难的。即使是内核中的union文件系统,
overlayfs
,也无法提供完整的POSIX语义。您需要LD_PRELOAD来钩住应用程序。要钩住第三方库,只需在库之前加载钩子(或者将其放在可执行文件中)
假设库从libc调用
open
,而不是直接调用相应的系统调用,并且它是以正常方式链接的,那么代码中的某个地方就有一个名为open
的函数。让它从libc调用open
(RTLD\u NEXT
或其他任何东西)。第三方库(当然还有所有其他库)会将其open
符号解析为您的函数 听起来你的处境很麻烦。下面简单提到的大多数解决方案都保证会干扰SELinux,所以不要相信我的话
使用strace
调试自己的进程以拦截open
是普通Linux上常见的解决方案之一。我不确定它是否能在安卓系统中工作;在某些新版本中启动的不可调试应用程序(如果尚未被禁止的话)可能会被禁止使用
seccomp bpf是另一种可能性。可能在较旧的安卓版本上不可用,但由于安卓O seccomp将成为安卓安全装备的保证部分。在仅警告模式下拦截open
,并在发生有趣的事情时(通过调试或信号)将控制权交还给自己
如果按需打开/data/anr/traces.txt
,您应该能够通过使用inotify或通过轮询查看/proc/self/fd/
的内容来观察到这一点。您可以通过设置打开线程的io精细度来减少竞争的影响
所有这些都只是部分解决方案,您可能仍然需要解码实际发生的open
syscall(strace源代码可能有助于strace/seccomp解决方案,readlink for/proc/self/fd/
)并据此采取行动(dup2,正如您已经提到的)
“只写日志文件”在库中硬编码
是否可以修改库/可执行文件数据段的内存?Afaik
mprotect
和PROTECT\u EXEC
尤其受到严格限制,但至少允许使用mmap(以支持JIT编译器等)。也许可以编造一些东西来在适当的位置编辑字符串常量(只要这样做是可能的和允许的,我自己对此不确定)。我觉得对LD\u PRELOAD
的反对是非技术性的。它在原则上可能有效,但如果站点策略不允许使用它,这并不重要。哦,我对我的问题描述得很糟糕,因为我错过了这样的场景。我不能使用动态链接器的LD_PRELOAD
和任何技巧,因为没有机会在应该监视的库之前加载任何自定义代码。请参阅编辑后的问题。“没有机会加载任何应监视的库之前的自定义代码”您的意思不太清楚。“假设我们有一个可能会打开()某个第三方库的进程”。如果你能控制这个过程,你就被设置好了。如果不是,那么用一种奇怪的方式来描述这种情况。整个程序是第三方的。与其他操作系统相比,Linux使这一点相对困难。微软的分层驱动架构使它相对容易。许多Windows驱动程序手册都包含强制加密文件系统的驱动程序示例。我从未见过Linux中分层的好例子。在当前的设计下,这可能是不可能的。这可能是重复的:。在40161522问题中,他不能使用LD_PRELOAD
,因为这对他来说不可靠。@jww很好的建议,但L