WH_JOURRNALRECORD 的 SetWindowsHookEx 在 Vista/Windows 7 下失败

发布于 2025-01-03 14:02:12 字数 1439 浏览 1 评论 0原文

我正在准备一个 Delphi 模块,它在线程中设置一个钩子来记录宏:

FHandleRec  := SetWindowsHookEx(WH_JOURNALRECORD, FRecordProc, HInstance, 0);
FHandlePlay := SetWindowsHookEx(WH_JOURNALPLAYBACK, FPlayProc, HInstance, 0);

在 WinXP 上工作正常,但在 Vista/Windows 7 上失败,并显示 ERROR_ACCESS_DENIED。 我在 Google 中找到了()指的是(那个)。报价:

较低权限的进程不能:...使用日志挂钩来监视 更高权限的进程。

尝试未成功:

  1. 以管理员身份运行应用程序。可能线程已启动 权限低于主线程(虽然我不是 100% 当然)
  2. 使用管理员安全上下文模拟线程 也没有帮助。

代码示例:

if LogonUser(PWideChar(sAdminUser), PWideChar(sDomain), PWideChar(sPwd),
             LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT, hToken) then 
begin  
  if not ImpersonateLoggedOnUser(hToken) then
    raise Exception.Create('Error impersonating the user');
end;
FHandleRec := SetWindowsHookEx(WH_JOURNALRECORD, FRecordProc, HInstance, 0);

LogonUserImpersonateLoggedOnUser 执行时没有错误。

其他可以尝试的可能性:

  1. 永久关闭 UAC。这有帮助,但我无法强制该模块 用户这样做。
  2. 模块客户签署应用程序并将其放入受信任的应用程序中 地点。没有尝试过,但这使模块变得非常复杂 供用户使用。
  3. 将模块放入某个已签名的应用程序中并分发 EXE。那 会破坏一些核心功能。

您能否显示在 Visa/Windows 7 下设置挂钩的代码或建议工作解决方案?

I am preparing a Delphi module, which sets a hook in a thread to record a macro:

FHandleRec  := SetWindowsHookEx(WH_JOURNALRECORD, FRecordProc, HInstance, 0);
FHandlePlay := SetWindowsHookEx(WH_JOURNALPLAYBACK, FPlayProc, HInstance, 0);

That works fine on WinXP, but on Vista/Windows 7 fails with ERROR_ACCESS_DENIED.
I have found in Google (this) referring (that). The quote:

A lower privilege process cannot: … Use Journal hooks to monitor a
higher privilege process.

Tried without success:

  1. Run application as administrator. Probably the thread is started
    with lower privileges than the main thread (though I am not 100%
    sure)
  2. Impersonating the thread with administrator security context
    doesn’t help either.

The code sample:

if LogonUser(PWideChar(sAdminUser), PWideChar(sDomain), PWideChar(sPwd),
             LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT, hToken) then 
begin  
  if not ImpersonateLoggedOnUser(hToken) then
    raise Exception.Create('Error impersonating the user');
end;
FHandleRec := SetWindowsHookEx(WH_JOURNALRECORD, FRecordProc, HInstance, 0);

LogonUser and ImpersonateLoggedOnUser execute without errors.

Other possibilities to try:

  1. Turn UAC OFF permanently. This helps, but I cannot force the module
    users to do that.
  2. A module customer signs an application and put it in a trusted
    location. Not tried that, but that radically complicates the module
    usage for the users.
  3. Put the module into some signed application and distribute EXE. That
    will break some core functionality.

Could you please show the code that is setting the hook under Visa / Windows 7 or suggest the working solution ?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

本王不退位尔等都是臣 2025-01-10 14:02:12

更仔细地再次阅读该文章的“用户界面权限隔离”部分。它指的是完整性级别,而不是用户权限。这就是为什么冒充其他用户并不能解决问题。完整性级别是在进程首次启动时建立的,并且无法在代码中动态更改。

用户界面权限隔离(UIPI)是机制之一
这有助于隔离以完全管理员身份运行的进程
以低于管理员级别的帐户运行的进程
相同的交互式桌面。 UIPI 特定于窗口和
图形子系统,称为 USER,支持 Windows 和用户
界面控制。 UIPI 防止低权限应用程序
使用 Windows 消息将输入从一个进程发送到更高的进程
特权进程。将输入从一个进程发送到另一个进程允许
在没有用户的情况下将输入注入到另一个进程的进程
提供键盘或鼠标操作。

Windows Vista通过定义一组用户界面来实现UIPI
以分层方式的特权级别。级别的性质
是这样的,更高的权限级别可以发送窗口消息到
运行在较低级别的应用程序。然而,较低的水平不能
将窗口消息发送到运行在更高级别的应用程序窗口。

用户界面权限级别位于进程级别。当一个
进程初始化后,用户子系统调用安全
子系统来确定分配的桌面完整性级别
进程的安全访问令牌。桌面完整性级别由以下设置
进程创建时的安全子系统
改变。因此,用户界面权限级别也由
进程创建时的用户子系统并且不会更改。

标准用户运行的所有应用程序都具有相同的用户界面
特权级别。 UIPI 不会干扰或改变
具有相同权限级别的应用程序之间的窗口消息传递。
UIPI 对属于以下组织成员的用户生效
管理员组,并且可能正在运行应用程序作为标准
用户(有时称为具有过滤访问令牌的进程)
以及使用完整管理员访问令牌运行的进程
相同的桌面。
UIPI 防止低权限进程
通过阻止列出的行为来访问更高权限的进程
如下。

  • 使用日志挂钩来监控更高权限的进程。

根据本文,您的应用程序需要一个指定 requestedExecutionLevel=requireAdministrator 的 UAC 清单uiAccess=True。 UIAccess 权限很重要:

通过在requestedPrivileges属性中指定UIAccess=”true”,
该应用程序声明需要绕过 UIPI 限制
...
使用 UIAccess 权限启动的进程:

  • 可以设置日志挂钩。

Read the "User Interface Privilege Isolation" section of that article again more carefully. It is referring to integrity levels, not user permissions. That is why impersonating another user does not solve the problem. The integrity level is established when the process first starts and cannot be changed dynamically in code.

User Interface Privilege Isolation (UIPI) is one of the mechanisms
that helps isolate processes running as a full administrator from
processes running as an account lower than an administrator on the
same interactive desktop. UIPI is specific to the windowing and
graphics subsystem, known as USER, that supports windows and user
interface controls. UIPI prevents a lower privilege application from
using Windows messages to send input from one process to a higher
privilege process. Sending input from one process to another allows a
process to inject input into another process without the user
providing keyboard or mouse actions.

Windows Vista implements UIPI by defining a set of user interface
privilege levels in a hierarchical fashion. The nature of the levels
is such that higher privilege levels can send window messages to
applications running at lower levels. However, lower levels cannot
send window messages to application windows running at higher levels.

The user interface privilege level is at the process level. When a
process is initialized, the User subsystem calls into the security
subsystem to determine the desktop integrity level assigned in the
process’s security access token. The desktop integrity level is set by
the security subsystem when the process is created and does not
change. Therefore, the user interface privilege level is also set by
the User subsystem when the process is created and does not change.

All applications run by a standard user have the same user interface
privilege level. UIPI does not interfere or change the behavior of
window messaging between applications at the same privilege level.
UIPI comes into effect for a user who is a member of the
administrators group and may be running applications as a standard
user (sometimes referred to as a process with a filtered access token)
and also processes running with a full administrator access token on
the same desktop.
UIPI prevents lower privilege processes from
accessing higher privilege processes by blocking the behavior listed
below.

  • Use Journal hooks to monitor a higher privilege process.

According to this article, your app needs a UAC manifest that specifies both requestedExecutionLevel=requireAdministrator and uiAccess=True. The UIAccess right is important:

By specifying UIAccess=”true” in the requestedPrivileges attribute,
the application is stating a requirement to bypass UIPI restrictions
...
A process that is launched with UIAccess rights:

  • Can set journal hooks.
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文