我已经使用 mhook library
编写了一个 Hook dll 。在特殊情况下 NtOpenFile()
当 std::wstring
时失败定义为stack var
。在 heap
上定义它代码是working
.
代码运行没有问题,除非某个 win32 application
(我们称之为 nuisance.exe)尝试打开现有的测试文件(如 c:\temp\anyfile.log) access fails
。通常会返回 STATUS_INVALID_ACL (0xC0000077)。
我有reduced my code
一行一行最后发现错误发生在被调用函数中定义了 std::wstring 时(下面的示例)。每次在不同操作系统上都会发生该错误
NTSTATUS NtOpenFileApiHook::NtOpenFileHook(PHANDLE FileHandle,
ACCESS_MASK DesiredAccess,
POBJECT_ATTRIBUTES ObjectAttributes,
PIO_STATUS_BLOCK IoStatusBlock,
ULONG ShareAccess,
ULONG OpenOptions
)
{
NTSTATUS Status = STATUS_SUCCESS;
// using this function the call will fail
AfterThis_NtOpenFile_WillFail();
// using this function INSTEAD the call will work
AfterThis_NtOpenFile_WillWork();
// calling the real NtOpenFile using a pointer
// nothing was changed hier, the original parameters are passed
Status = RealNtOpenFile(FileHandle, ...);
return Status;
}
int AfterThis_NtOpenFile_WillFail()
{
std::wstring String = L"";
return 0;
}
int AfterThis_NtOpenFile_WillWork()
{
std::wstring * pString = new std::wstring();
pString->assign(L"");
delete pString;
return 0;
}
我已经为这次通话修复了这个问题。但我担心其他情况下的其他功能可能会失败,所以我正在寻找原因和(可能)解决方案。
Nuisance.exe 是一个 C# 应用程序,具有默认堆栈大小,调用一个我一无所知的 win32 dll。
最佳答案
如果 Nuisance.exe 是一个 C++ 应用程序,我想它会以与此类似的方式调用 NtOpenFile,在覆盖的堆栈上分配指针参数之一:
POBJECT_ATTRIBUTES MakeObjectAttributes()
{
POBJECT_ATTRIBUTES oa = {...};
return &oa; // Pointer to stack variable - UB
}
...
NtOpenFile(..., MakeObjectAttributes(), ...)
STATUS_INVALID_ACL (0xC0000077)
错误可能表明 OBJECT_ATTRIBUTES
中的 SecurityDescriptor
是以这种方式分配的。
然后,AfterThis_NtOpenFile_WillFail
使用了多少堆栈很重要,而且它比 AfterThis_NtOpenFile_WillWork
多,因为 std::wstring
会更大由于小字符串优化,不仅仅是几个指针。
如果调用链始终相同,则损坏可能是确定性的。
我不知道 C# 中是否可以实现与临时返回地址等效的代码。但 DLL 可能采用 C/C++ 或允许随意指针的类似语言。
为了证明/反证堆栈的作用,请尝试在堆栈上分配具有 std::wstring
大小的其他数据。更精确的证据可以是检查传递的指针以查看它们是否指向即将被覆盖的堆栈区域。
关于c++ - 当 std::wstring 在堆栈上定义时,Hooked NtOpenFile 失败,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24409822/