c++ - 当 std::wstring 在堆栈上定义时,Hooked NtOpenFile 失败

标签 c++ winapi heap-memory stack-memory api-hook

我已经使用 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/

相关文章:

c++ - Unresolved Externals, 未解析的外部符号 LNK 1120

C++ double 不能等于两个 int 除法

c++ - C++ 程序中的 TCHAR 和未解析的外部符号 (LNK2019) 错误?

C++堆栈数组限制?

c - dev c++ 堆栈算法中的 SIGSEGV(段错误)错误(Lenguage c)

c++ - C/C++中随机数生成器的实现

c++ - 软件模型设计

c++ - 在没有new的情况下在堆上创建一个对象

Windows 资源管理器外壳扩展 : create file and enter "rename" mode

windows - Win32 ASM 程序不向命令行打印任何内容