我已经使用mhook library
编写了一个挂钩dll。在特殊情况下,当std::wstring
被定义为stack var
时,NtOpenFile()
失败。在heap
上定义它,代码为working
。
除了当某个win32 application
(让我们称之为noublish.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是一个带有默认stacksize的C#应用程序,它调用一个win32 dll,对此我一无所知。
如果Nuisance.exe是一个C++应用程序,我可以想象它以类似的方式调用NtOpenFile,在覆盖的堆栈上分配一个指针参数:
POBJECT_ATTRIBUTES MakeObjectAttributes()
{
POBJECT_ATTRIBUTES oa = {...};
return &oa; // Pointer to stack variable - UB
}
...
NtOpenFile(..., MakeObjectAttributes(), ...)
CCD_ 10错误可能表明CCD_ 12中的CCD_。
那么,AfterThis_NtOpenFile_WillFail
使用了多少堆栈就很重要了,而且它比AfterThis_NtOpenFile_WillWork
多,因为由于小字符串优化,std::wstring
将大于几个指针。
如果调用链始终相同,则损坏可能是确定的。
我不知道在C#中是否可以使用与返回临时地址等效的代码。但是DLL可以是C/C++或类似的语言,允许对指针进行数据处理。
要证明/反驳堆栈的作用,请尝试在具有std::wstring
大小的堆栈上分配其他数据。更精确的证明可以是检查传递的指针,看看它们是否指向即将被覆盖的堆栈区域。