WH_JOURNALRECORD的SetWindowsHookEx在Vista / Windows 7下失败

时间:2012-02-06 19:02:39

标签: delphi winapi windows-7 windows-vista setwindowshookex

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

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

在WinXP上运行正常,但在Vista / Windows 7上运行ERROR_ACCESS_DENIED失败。 我在Google(this)中找到了引用(that)。引用:

  

较低权限进程不能:...使用Journal钩子来监视a   更高的特权流程。

尝试没有成功:

  1. 以管理员身份运行应用程序。可能线程已启动 权限低于主线程(虽然我不是100% 肯定)
  2. 使用管理员安全上下文模拟线程 也无济于事。
  3. 代码示例:

    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。那 将打破一些核心功能。
    4. 您能否在Visa / Windows 7下显示设置挂钩的代码或建议使用解决方案?

1 个答案:

答案 0 :(得分:8)

再次仔细阅读that article的“用户界面权限隔离”部分。它指的是完整性级别,而不是用户权限。这就是冒充其他用户无法解决问题的原因。 完整性级别是在流程首次启动时建立的,无法在代码中动态更改。

  

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

     

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

     

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

     

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

     
      
  • 使用Journal钩子监视更高权限的过程。
  •   

根据this article,您的应用需要一个指定requestedExecutionLevel=requireAdministratoruiAccess=True的UAC清单。 UIAccess权利很重要:

  

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

     
      
  • 可以设置日记挂钩。
  •