C++ DLL中实现指定文件操作忽略Virtual File System(VFS)的可行性问询
解答
完全可以从DLL层面实现该需求,具体实现逻辑和可选方案如下:
核心原理
普通应用级的VFS几乎都是通过用户态API Hook实现拦截:要么Hook Win32层的CreateFileW/ReadFile等文件接口,要么Hook标准库的文件操作底层调用,只要你的DLL内的文件操作不走被Hook的接口,就能直接访问真实文件。
可选实现方案
方案1:直接调用系统原生API(最稳妥)
跳过std::filesystem封装,直接调用ntdll层的原生文件操作接口(如NtCreateFile、NtQueryInformationFile、NtReadFile、NtWriteFile),几乎没有VFS会Hook到ntdll的原生内核调用层面,100%能绕过用户态VFS拦截。
示例代码(Windows平台):#include <windows.h> #include <winternl.h> typedef NTSTATUS(WINAPI* PFN_NTCREATEFILE)( PHANDLE FileHandle, ACCESS_MASK DesiredAccess, POBJECT_ATTRIBUTES ObjectAttributes, PIO_STATUS_BLOCK IoStatusBlock, PLARGE_INTEGER AllocationSize, ULONG FileAttributes, ULONG ShareAccess, ULONG CreateDisposition, ULONG CreateOptions, PVOID EaBuffer, ULONG EaLength ); // 获取原生API地址 auto pNtCreateFile = reinterpret_cast<PFN_NTCREATEFILE>(GetProcAddress(GetModuleHandleW(L"ntdll.dll"), "NtCreateFile")); bool access_real_file(const wchar_t* nt_path) { HANDLE hFile = nullptr; UNICODE_STRING u_path; RtlInitUnicodeString(&u_path, nt_path); OBJECT_ATTRIBUTES obj_attr; InitializeObjectAttributes(&obj_attr, &u_path, OBJ_CASE_INSENSITIVE, nullptr, nullptr); IO_STATUS_BLOCK io_status = {}; NTSTATUS status = pNtCreateFile(&hFile, GENERIC_READ, &obj_attr, &io_status, nullptr, FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ, FILE_OPEN, 0, nullptr, 0); if (NT_SUCCESS(status)) { // 后续读写、校验都走原生接口,完全绕过VFS CloseHandle(hFile); return true; } return false; }方案2:修复当前DLL的导入地址表
如果VFS是通过IAT Hook实现的拦截,你可以手动扫描当前DLL的IAT表,把所有文件操作相关API的地址重置为kernel32.dll/ntdll.dll中的原始地址,修复完成后,不管你用std::filesystem还是普通Win32文件API,都会直接调用系统原生接口,不会被VFS截获。方案3:自定义
如果你不想改上层已经用std::filesystem底层实现std::filesystem写好的代码,可以基于原生API自己实现一套符合std::filesystem要求的底层文件系统接口,替换STL默认的底层实现,上层业务代码不需要做任何修改就能直接访问真实文件。
注意事项
只有当应用A的VFS是内核级文件系统过滤器驱动实现时,上述用户态绕过方案才会失效。但绝大多数普通应用的VFS都是用户态Hook实现,上述所有方案都适用。
内容的提问来源于stack exchange,提问作者Garlic2394
相关产品推荐
相关产品推荐

