隐藏文件不被其他程序发现

7

我需要让一个文件对其他程序不可见。例如,当另一个程序获取文件夹中的文件列表时,我想让其中一个特定的文件不显示出来。我正在将一个DLL注入到进程中,从中运行我的代码,并隐藏文件系统中的DLL文件。我使用的是Microsoft Visual C++ 2010和Windows 7。


这听起来相当靠不住!我敢猜测,这是不可能的。 - Oliver Charlesworth
2个回答

11

如你所提到的,您需要拦截文件/文件夹枚举API并从枚举结果中过滤出特定的文件/文件夹以便“隐藏”它。这可以在用户模式或内核模式下完成。

用户模式:用户模式钩子涉及DLL注入。有许多地方可以进行钩子:

  • 可执行文件的IAT钩子:查找目标进程的导入地址表中的FindXxx条目,并用注入DLL中的跳转函数的地址覆盖它。
  • 被可执行文件加载的DLL的EAT钩子:查找已加载的DLL(在此情况下是kernel32.dll)的导出地址表中的FindXxx API的条目,并用注入DLL中的跳转函数的地址覆盖它。
  • 行内钩子:使用 JMP 将一个已加载的 DLL 中 API 代码的前几个指令覆盖为跳转到您的跳转函数的 JMP。

一般来说,用户模式可能会变得“丑陋”(难以管理),因为如果要进行系统范围的钩子(或者至少在 Explorer.exe 或目标应用程序中进行钩子),则需要将 DLL 注入所有正在运行的进程中。许多应用程序(如安全软件)都有保护机制来检测和拒绝 DLL 注入。

实现用户模式钩子的更干净的方法是在 NTDLL.dll 中挂钩 API(使用 EAT 或内联钩子)。所有其他 API(如 FindFirstFile/FindNextFile)最终都调用由 NTDLL.dll 提供的等效 NtXxx API(如 NtQueryDirectoryFile)。NtXxx API 是通过执行 INT 2E/SYSENTER 跳转到内核模式的点。

内核模式:这需要编写驱动程序。同样,在内核模式下,有许多地方可以安装钩子:

  • SSDT钩子:通过将对应的 SSDT 索引用您的驱动程序中的跳转函数地址覆盖所需的 ZwXxx API(在此情况下是ZwQueryDirectoryFile)安装 SSDT 钩子。
  • 内核行内钩子:使用 JMP 将由内核导出的 NT 内核 API 的前几个指令覆盖为指向您的驱动程序中的跳转函数的 JMP。
  • 文件系统过滤驱动程序:这是一种更干净的方法,不需要使用钩子。安装文件系统过滤器驱动程序并拦截读/写/枚举 IOCTL 并过滤结果以隐藏/锁定特定文件/文件夹。

内核模式钩子往往更干净,因为它们通常安装在一个“集中的位置”。但是,您应该非常小心,因为驱动程序代码中的小错误/处理不当可能会导致蓝屏崩溃。

PS: 有许多钩子库或框架可供使用,可以方便地编写代码。其中一些流行的包括:
http://www.madshi.net/madCodeHookDescription.htm
http://easyhook.codeplex.com/

PPS: 使用这种技术未经用户同意来隐藏文件/文件夹可能是一个值得质疑的行为,并且可能会导致问题(还记得Sony DRM保护软件的问题吗?;))。这就是rootkits所做的!有许多用户模式和内核模式的rootkits使用上述技术来隐藏文件/文件夹。有各种反rootkit软件可用于检测和恢复上述所有类型的钩子。许多防病毒软件在检测到此类rootkit行为时会发出警报(如API hooking、隐藏文件、SSDT hooks等)

一些资源:
http://www.codeproject.com/KB/threads/APIHooking.aspx
http://www.codeproject.com/KB/DLL/funapihook.aspx
http://www.codeproject.com/KB/system/api_spying_hack.aspx
http://www.codeproject.com/KB/system/hide-driver.aspx
http://www.uc-forum.com/forum/c-and-c/59147-writing-drivers-perform-kernel-level-ssdt-hooking.html
http://www.security.org.sg/code/apihookcheck.html


0
最简单的方法是使用Microsoft Detours覆盖所需的函数。 它也可以用于注入DLL,但是您已经解决了这个问题。 如果其他进程使用的特定函数对您来说是已知的,请挂接在该函数上。 如果没有,则需要挂接用于列出文件或打开文件的所有函数的基本构建块。 只需要挂钩CreateFile / FindFirst / FindFirstFile等函数即可,因为它们只调用内部函数。 例如,如果您挂钩实际映射到CreateFileA的CreateFile,则该进程仍将能够使用CreateFileW访问文件。 因此,您需要挂钩NtCreateFile和朋友。 但我猜您知道正在处理哪个进程,因此也知道要干扰哪些函数。

我已经钩取了FindFirstFile和FindFirstFileEx,但当程序列出文件时它们并没有被调用。它可能在使用其他函数吗?当你说“我猜你知道你正在搞什么进程,所以你知道……”实际上这就是问题所在,因为我可以钩取函数,但我不确定应该钩取哪个函数。 - James Feder
你是否同时使用了FindFirstFileA和FindFirstFileW?你尝试过API Monitor http://www.apimonitor.com/吗?如果你不知道它在使用什么,也不想反汇编来深入挖掘,你总是可以用最低级别的函数NtQueryDirectoryFile和可能的NtQueryDirectoryObject来捕获它们。 - kichik
不,我没有钩取FindFirstFileA和W。而NtQueryDirectory*是一个好主意,我之前并不知道,谢谢。 - James Feder
说句实话,最好的方法是在 OllyDbg/IDA 中打开它并找出它到底在调用什么。这样可以避免编写过于通用和复杂的代码。 - kichik
我已经有了,但代码很复杂,我无法弄清它调用了什么。此外,程序中的所有导出都被剥离了,这使得它更加困难。 - James Feder

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接