从 UWP 应用程序窗口的 Windows.UI.Core.CoreWindow 获取 win32 消息

Mah*_*asi 3 .net c# winapi

WH_CALLWNDPROC我正在尝试通过、WH_CALLWNDPROCRET和上的挂钩获取特定窗口的指针 Win32 消息WH_GETMESSAGE

SetWindowsHookEx在 C++ dll 中使用来挂钩和接收消息。

unsigned long processID = 0;
unsigned long threadID = GetWindowThreadProcessId(hWnd, &processID);

g_hhkGetMsg = SetWindowsHookEx(WH_GETMESSAGE,
    GetMsgProc,
    g_hinstDLL,
    threadID);
Run Code Online (Sandbox Code Playgroud)

这适用于许多窗口,但不适用于CoreWindowUWP 窗口。

每个 UWP 应用窗口都有这样的结构:UWP窗口结构

挂钩到 ApplicationFrameWindow 工作正常,但挂钩Windows.UI.Core.CoreWindow不起作用。(SetWindowsHookEx显示成功,但我在回调中没有收到任何消息)

但是,Spy++能够从CoreWindow. (CoreWindow接收WM_POINTER消息,所以我需要订阅该窗口)

考虑到问题可能出在我的代码上,我还尝试了开源工具MyLiteSpy,看看它是否可以捕获来自 CoreWindow 的消息。它无法捕获任何内容,就像我的示例代码一样。(但是 MyLiteSpy 能够从同一 UWP 应用程序的 ApplicationFrameWindow 获取消息,我的代码和 Spy++ 也可以)

在此输入图像描述

有趣的是,这篇关于 Spy++ 的(旧)博客文章说他们使用与我和 MyLiteSpy 相同的三个钩子,但它正在获取我的代码无法接收的消息。

这里有什么区别呢?知道为什么会发生这种情况吗?

(Spy++ 是否使用除上述三个之外的钩子?该博客文章写于 2007 年,所以情况可能有所改变)

RbM*_*bMm 5

Windows.UI.Core.CoreWindow类的窗口通常是沉浸式窗口。为了能够枚举这样的顶级窗口,我们需要在清单中具有disableWindowFiltering。它禁用窗口过滤,因此您可以从桌面枚举(通过)沉浸式窗口。EnumWindows但说直接调用- 即使清单中没有disableWindowFilteringFindWindowW(L"Windows.UI.Core.CoreWindow", L"Start");也不会失败。然而,这部分仅与您的应用程序的可见性沉浸式窗口有关。EnumWindows

WH_GETMESSAGE另一个任务为此类窗口设置挂钩。这里的问题是这个窗口通常属于Windows Store应用程序(AppContainer)进程。

Windows 应用商店应用程序开发:如果dwThreadId为零,则不会在 Windows 应用商店应用程序进程和 Windows 运行时代理进程的进程内加载窗口挂钩 DLL,除非它们是由UIAccess进程(辅助工具)安装的。

所以我们需要uiAccess在清单(例如)中将 或 设置为 true ,或者在调用中<requestedExecutionLevel level="requireAdministrator" uiAccess="true" />不将其设置为 0 。我们可以通过dwThreadIdSetWindowsHookExdwThreadIdGetWindowThreadProcessId

WH_GETMESSAGE钩子始终处于进程钩子中。因此,如果我们为另一个进程调用它 - 钩子过程必须位于 dll 中,它将被加载到目标进程。这里是主要问题 - 如何将 dll 加载到 Windows 应用商店应用程序 (AppContainer) 进程。

我简单地使用 self dll 检查这一点 - 尝试为Windows.UI.Core.CoreWindow::Calculator窗口设置挂钩。的调用SetWindowsHookEx(WH_GETMESSAGE, ..)是可以的,并且在Calculator.exe中调用LoadLibraryExW了我的 dll,但是此调用在内部失败NtQueryAttributesFile并出现 error STATUS_ACCESS_DENIED。好的,Appcontainer 是一个非常受限制的进程,所以我尝试更改我的 dll 上的安全描述符。将其设置为(给予内置(本地)管理员完全访问权限,并对在应用程序包上下文 ( - ) 和每个人 ( )"D:P(A;;FA;;;BA)(A;;FXFR;;;WD)(A;;FXFR;;;AC)S:P(ML;;NW;;;LW)"中运行的所有应用程序进行读取执行访问。继续执行此操作,但无论如何都无法使用代码调用我的 DLL (-检测到系统二进制文件中的错误)之后调用(从ntdll.dll导出的函数)SDDL_ALL_APP_PACKAGES"AC""WD"LoadLibraryExWZwCreateSectionSTATUS_SYSTEM_NEEDS_REMEDIATIONC000047ELLdrAppxHandleIntegrityFailure

在此输入图像描述 在此输入图像描述

因此,要将 DLL 加载到 Windows 应用商店应用程序 (Appcontainer),必须对它进行签名。接下来是来自内核端调用堆栈

CI!KappxpNotifyNonPackagedFile
CI!KappxNotifyIntegrityFailureInPackagedProcess
CI!CipReportAndReprieveUMCIFailure
CI!CiValidateImageHeader
nt!SeValidateImageHeader
nt!MiValidateSectionCreate
nt!MiCreateNewSection
nt!MiCreateImageOrDataSection
nt!MiCreateSection
Run Code Online (Sandbox Code Playgroud)

有趣的是,如果检查失败CI.DLL内部KappxpNotifyNonPackagedFile写入文件名和哈希值到注册表HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\AppModel\StateChange- BinaryName( REG_SZ) 和BinaryHash( REG_BINARY)下

在此输入图像描述

如果 Spyxx - 它使用签名的 dll -pyxxhk[_amd64].dll - 加载此 dll(如果允许所有应用程序包访问它)即可正常处理。因此Spy++也有可能从 Appcontainer 应用程序收集消息。但在我的研究中,Spy++调用SetWindowsHookExW首先dwThreadId设置为零。因此,spyxxhk[_amd64].dll将不会注入到 Windows 应用商店应用程序中。每次都需要使用非 0 dwThreadId并且在 dll 上有特殊的安全描述符。