日志记录挂钩的挂钩过程从未被调用

2024-02-16

我正在尝试创建一个简单的应用程序来记录和播放一系列键盘和鼠标命令(宏)。阅读文档并得出结论,最合适的实现(如果不是唯一的实现)是设置 Windows 日志记录挂钩(WH_JOURNALRECORD)并用日志回放一个(WH_JOURNAL_PLAYBACK).

根据文档,这些挂钩不需要驻留在 DLL 中,而是可以位于可执行文件(应用程序)中。因此,我让 Visual Studio 为我创建了一个简单的 Win32 应用程序。这是一个非常经典的应用程序,注册窗口类、创建窗口并运行消息循环。该文档还提到了钩子程序WH_JOURNALRECORD/WH_JOURNAL_PLAYBACK钩子在设置它们的线程的上下文中运行。但是,它没有具体提及该线程应该做什么,例如运行消息循环、在可警报状态下睡眠或什么。所以我只是设置钩子并运行消息循环 - 它是应用程序的主线程,也是唯一的线程。我发现的一些代码示例也是这样做的,尽管它们现在似乎无法工作,因为它们已经很旧了,而且一些 Windows 安全更新使事情变得更加困难。

我相信我已经采取了在一些示例和帖子中找到的所有必要步骤:

  • 设置清单选项“UAC执行级别" to "requireAdministrator (/level='requireAdministrator')" and "UAC绕过UI保护" to "是 (/uiAccess='true')".
  • 创建并安装证书 - 应用程序在构建后使用它进行签名。
  • 可执行文件被复制到 System32(受信任的文件夹)并从那里“以管理员身份”运行。 如果不执行上述操作,挂钩安装将失败,错误代码为 5(访问被拒绝)。

我已经成功(?)安装了WH_JOURNALRECORD hook (SetWindowsHookEx()返回一个非零句柄),但是不会调用钩子过程。

下面是我的代码(我省略了窗口类注册、窗口创建、窗口过程和关于对话框的内容,因为其中没有什么有趣或特别的东西 - 它们只是做准系统):

// Not sure if these are needed, found it in some code samples
#pragma comment(linker, "/SECTION:.SHARED,RWS")
#pragma data_seg(".SHARED")
HHOOK hhJournal = NULL;
#pragma data_seg()

// Not sure if the Journal proc needs to be exported
__declspec(dllexport) LRESULT CALLBACK _JournalRProc(_In_ int code, _In_ WPARAM wParam, _In_ LPARAM lParam)
{
    Beep(1000, 30); // Clumsy way to trace the JournalRProc calls

    return CallNextHookEx(NULL, code, wParam, lParam);
}

void AddKMHooks(HMODULE _hMod)
{
    if (hhJournal) return;
    MessageBox(NULL, "Adding Hooks", szTitle, MB_OK | MB_ICONINFORMATION | MB_TASKMODAL);
    hhJournal = SetWindowsHookEx(WH_JOURNALRECORD, _JournalRProc, _hMod, 0);
    if (!hhJournal)
    {
        CHAR s[100];
        wsprintf(s, "Record Journal Hook Failed!\nThe Error-Code was %d", GetLastError());
        MessageBox(NULL, s, szTitle, MB_OK | MB_ICONSTOP | MB_TASKMODAL);
    }
}

void RemoveKMHooks()
{
    if (!hhJournal) return;
    MessageBox(NULL, "Removing Hooks", szTitle, MB_OK | MB_ICONINFORMATION | MB_TASKMODAL);
    UnhookWindowsHookEx(hhJournal);
    hhJournal = NULL;
}

int APIENTRY wWinMain(_In_ HINSTANCE hInstance,
                     _In_opt_ HINSTANCE hPrevInstance,
                     _In_ LPWSTR    lpCmdLine,
                     _In_ int       nCmdShow)
{
    UNREFERENCED_PARAMETER(hPrevInstance);
    UNREFERENCED_PARAMETER(lpCmdLine);

    // TODO: Place code here.

    // Initialize global strings
    LoadString(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
    LoadString(hInstance, IDC_KMRECORD, szWindowClass, MAX_LOADSTRING);
    MyRegisterClass(hInstance);

    // Perform application initialization:
    if (!InitInstance(hInstance, nCmdShow)) return FALSE;

    HACCEL hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_KMRECORD));

    AddKMHooks(hInstance);
    // Calling AddKMHooks(GetModuleHandle(NULL)) instead, delivers the same results

    MSG msg;

    // Main message loop:
    while (GetMessage(&msg, nullptr, 0, 0))
    {
        if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
        {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }
    }
    // Once the hook has is set the GetMessage() call above 
    // always returns a WM_TIMER message with a timer ID of 1,
    // posted to the queue with the PostMessage() function,
    // as the Spy++ tool reports

    RemoveKMHooks();

    return (int) msg.wParam;
}

我用Spy++工具监控应用程序,发现当设置钩子时,应用程序会收到一系列连续的WM_TIMER计时器消息,计时器 ID 为 1,发布到队列中PostMessage()函数(Spy++ 中的 P)。据报告,这些消息的窗口句柄与主窗口属于同一应用程序和线程,其类名称为“UserAdapterWindowClass”。我的代码既不创建计时器,也不显式创建此类的任何窗口,因此显然这些是由系统创建的。此外,还有另一条消息,ID 为 0x0060(未知!),仅在第一次或第二次之后发布到同一窗口一次WM_TIMER one.

该应用程序似乎以某种方式“锁定”系统(录制、等待资源,或者什么?),直到我按 Alt+Ctrl+Del,文档说停止录制(我还没有实现某种机制来停止录制/随意卸载钩子,所以这是我目前使用的)。钩子过程似乎永远不会被调用,这就是我目前面临的问题。我考虑过检查code钩子过程中的参数并采取相应的行动,但我还没有接近这一点,因为该过程从未被调用 - 因此它不会产生任何效果 - 所以我只是调用CallNextHookEx()在那里(并假设它会运作良好)。

Notes:

  • 钩子过程有时可能只被调用一次,但这种情况相当罕见(几乎不可重现)并且绝对不一致,所以我认为我不能依赖于此;这code参数为 0 (HC_ACTION)。但测试了它,并返回零或非零,或者调用CallNextHookEx()或不,根本没有区别。
  • 我还尝试在另一个线程中设置挂钩(在主线程开始处理消息后创建),然后该线程也运行消息循环,但我得到了完全相同的行为。

有人可以解释一下这里可能出了什么问题吗?还检查了其他一些帖子,特别是这些:WH_JOURRNALRECORD 的 SetWindowsHookEx 在 Vista/Windows 7 下失败 https://stackoverflow.com/questions/9165666/setwindowshookex-for-wh-journalrecord-fails-under-vista-windows-7 and Windows (C++) 中的 WH_JOURNALRECORD 挂钩 - 从未调用过回调。 https://stackoverflow.com/questions/3157212/wh-journalrecord-hook-in-windows-c-callback-never-called/3157256,但是找不到解决方案,而且我必须注意使用条件也不同。我所经历的最接近这个SetWindowsHookEx(WH_JOURRNALRECORD, ..) 有时会挂起系统 https://stackoverflow.com/questions/29335012/setwindowshookexwh-journalrecord-sometimes-hang-the-system尽管就我而言,这种情况总是会发生,而不仅仅是“有时”。

我将非常感谢任何帮助。

我已经上传了解决方案(源+ VS 文件,但不是 .exe、.obj.、.pch、.pdb 等文件,因此需要重建)here https://github.com/GCoves81/KbdMouseRecorderSource,如果有人想看的话。

先感谢您


EDIT:

在不同配置下测试应用程序。

  • 最初,该应用程序是在 Visual Studio 2017 中创建的,并在 Windows 10 Pro 32 位版本 1803、2 核 AMD 处理器计算机(本机上安装了 VS2017)下进行了测试。得到了上面描述的结果。
  • 然后在Windows 10 Pro 64位版本1903、4核AMD处理器电脑下进行测试。这台机器安装了一个非常旧版本的Visual Studio(尽管它没有以任何方式参与开发和测试)。安装证书并运行应用程序(均在另一台计算机上创建)。最初的结果是相同的(钩子过程从未被调用)。
  • 尝试从“PrivateCertStore”存储位置删除证书,只保留“受信任的根证书颁发机构”下的副本(这是我编写的批处理文件调用 makecert 和 certmgr 存储证书的方式,即在上述两个位置下) 。出乎意料,但它有效,当我移动鼠标时听到多次蜂鸣声!再次测试,添加/删除/移动证书,行为完全可重现:只需将证书安装在“受信任的根证书颁发机构”下,挂钩即可工作。
  • 然后在32位机器上重复上述测试。它在那里不起作用,应用程序像以前一样被“冻结”(仅获取 WM_TIMER 消息)。
  • 在64位机器上,卸载旧的VS版本和安装的相当多的Windows SDK版本,并安装VS 2019社区版。在 VS2019 中重建应用程序(重新创建并安装证书,并对可执行文件进行签名)。该应用程序现在无法在任何一台机器上运行(同样,钩子创建成功,但未调用钩子过程)。可能是 VS2019 安装或某些 Windows 更新导致了此问题。
  • 同样,在 32 位计算机上创建的应用程序/证书现在在任何一台计算机上都不起作用。

所以它一定是 Windows 模块或我不满足的一些有关证书的要求,导致了这种情况。在互联网上搜索了很多,但找不到证书必须符合哪些规范。例如,对格式、私钥或用途有什么要求(现在我已经检查了所有用途,尽管我也尝试过仅检查代码签名,这没有什么区别)。 makecert 实用程序现已弃用(文档建议使用 PowerShell 创建证书),但我不知道这是否与我的问题有关。

我只得出两个结论: - 证书必须安装在“PrivateCertStore”下,才能构建应用程序(否则签名失败)。可能是因为我在脚本中设置了 /s PrivateCertStore 选项。但, - 证书必须安装在“受信任的根证书颁发机构”下,应用程序才能运行(否则执行会失败,并出现拒绝访问错误)。


None

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

日志记录挂钩的挂钩过程从未被调用 的相关文章

  • 是否可以从 C++ 应用程序调用 C# 应用程序?

    我是一名编程学生 现在我已经上了两门 C 课程 这个学期我将参加我的第一门 C 课程 出于好奇 是否可以从 C 应用程序调用 C 应用程序 如果是的话 是否还可以检查运行该程序的计算机是否具有 NET框架 我只是很好奇 我想如果可能的话 这
  • c# 从另一个类中的另一个静态事件引发事件

    需要帮助从另一个班级调用事件 我有已声明事件的课程 public class MxPBaseGridView GridView public event AddNewItemsToPopUpMenuEventHandler AddNewIt
  • 叮当错误?命名空间模板类的朋友

    以下代码在 clang 下无法编译 但在 gcc 和 VS 下可以编译 template
  • while循环中的变量初始化

    我有一个可以分块读取文件的函数 public static DataObject ReadNextFile 数据对象看起来像这样 public DataObject public string Category get set And ot
  • 将日期时间转换为指定格式

    我有这个日期格式yy MM dd HH mm ss ex 12 02 21 10 56 09 问题是 当我尝试使用以下代码将其转换为不同格式时 CDate 12 02 21 10 56 09 ToString MMM dd yyyy HH
  • Docker 警告:无法从守护进程获取默认注册表端点

    在 Windows 10 上 当我调用 docker 命令时 docker pull mongo windowsservercore 我得到以下输出 Warning failed to get default registry endpoi
  • 在 C++11 中移出 stdpriority_queue 的元素

    最小的工作示例 include
  • 如何在win32中使用GetSaveFileName保存文件?

    我编写此代码是为了获取 fileName 来保存我的文件 include stdafx h include
  • 你好,我最近正在开发我的新游戏,我遇到了*无限跳跃*的问题

    所以基本上当我按跳跃 空格键时我会跳跃但是如果我连续按空格键它 只是跳啊跳啊跳等等 我不想要我只想它跳一次 code if Input GetKeyDown space isGrounded velocity y Mathf Sqrt ju
  • 通过 C# Mailkit / Mimekit 发送电子邮件,但出现服务器证书错误

    Visual Studio 2015 中的 0 代码 1 我正在使用 Mailkit 最新版本 1 18 1 1 从我自己的电子邮件服务器发送电子邮件 2 电子邮件服务器具有不受信任的自签名证书 3 我在代码中添加了以下两行 以忽略服务器证
  • 用于连接 DataTable 上的动态列的动态 LINQ

    我目前遇到的情况不确定如何继续 我有两个从数据库填充的数据表 我还有一个可用的列名称列表 可用于将这两个数据表连接在一起 我希望编写一组 LINQ 查询 这些查询将 显示两个数据表中的行 内部联接 用于从一个数据表更新另一个数据表 显示一个
  • Xamarin - SignalR 挂在连接上

    我正在尝试将我的 Xamarin 应用程序连接到托管在 Azure 上的 SignalR 后端 我遇到的问题是每次我在 HubConnection 上调用 StartAsync 时 它都会挂起客户端并且请求永远不会完成 我尝试通过应用程序进
  • 时间:2019-03-17 标签:c++fstream并发访问

    如果从不同的进程 线程同时访问文件会发生什么 据我所知 没有锁定文件的标准方法 只有操作系统特定的功能 就我而言 文件将被经常读取而很少写入 现在如果A打开一个文件进行读取 ifstream 并开始读取块 和B打开相同的文件进行写入 ofs
  • 如何在 C# 中获取 Json 数组?

    我有一个像这样的 Json 字符串 我想将它加载到 C 数组中 当我尝试这样做时 我收到异常 我的字符串 customerInformation customerId 123 CustomerName Age 39 Gender Male
  • C++ 到 C# 事件处理

    所以我有我的C WinForm 应用程序 我从中调用我的C CLI MFC dll图书馆 但也有一些events在我的 C 库上 甚至此事件也发生在该库的本机 非 CLI 部分 我需要从我的 C 应用程序调用一些代码 并获取一些有关此事件的
  • 使用多线程进行矩阵乘法?

    我应该使用线程将两个矩阵相乘 有两件事 当我运行程序时 我不断得到 0 我还收到消息错误 对于每个错误 它在粗体行上显示 警告 从不兼容的指针类型传递 printMatrix 的参数1 我尝试打印输出 还要注意 第一个粗体块 这是我解决问题
  • EnumDisplayDevices 与 WMI Win32_DesktopMonitor,如何检测活动监视器?

    对于我当前的 C 项目 我需要为在大量计算机上连接并处于活动状态的每个监视器检测一个唯一的字符串 研究指出了两种选择 使用 WMI 并查询 Win32 DesktopMonitor 以获取所有活动监视器 使用 PNPDeviceID 来唯一
  • 使用 xslt 将 xml 转换为 xsl-fo 时动态创建超链接?

    我想使用 xsl 文件在 PDF 报告中创建标题 如果源文件包含超链接 则应将其呈现为超链接 否则呈现为纯文本 例如 我的 xml 如下所示 a href http google com target blank This is the h
  • 如何在dll级别读取app.config? [复制]

    这个问题在这里已经有答案了 我在一个解决方案中有一个控制台应用程序项目和库项目 dll The 图书馆项目有 app config 文件 我在其中存储我在库中使用的一些键值对 控制台应用程序引用此 dll 我有另一个 app config
  • 使用 C# 动态创建按钮并按预定义的顺序放置它们

    NET 4 5 C 创建 Windows 窗体 我想动态创建和添加按钮并为其分配单击事件 但希望它们以特定的方式动态放置 就像图像一样 我的问题是如何以上述方式动态放置按钮 即 4x4 格式 一行 4 个按钮 4 列 但行数不受限制 是否可

随机推荐

  • 无法将 JSON 对象插入 Firebase 实时数据库

    我正在尝试将用户数据存储在我的 Firebase 数据库中 这是我处理 onClick 并将数据发送到数据库的代码 public void onClickStore final View view String name binding g
  • 停止观察reactjs中的文件夹变化

    我正在开发一个反应项目 用户可以在其中上传文件 我面临的问题是当我将文件上传到服务器并将该文件保存到位于公共文件夹中的名为 uploads 的文件夹中时 然后当此过程完成页面刷新 这是因为应用程序正在监视任何更改并刷新页面 我知道我可以通过
  • 尽管安装并加载了 reshape2,但仍找不到功能“cast”

    跟随哈德利 威克姆 Hadley Wickham 探索数据和模型的实用工具 http had co nz thesis 2 4 节中的示例 铸造熔融数据我越来越Error could not find function cast 我已经安装
  • 一键运行 Javascript 2 个函数

    我使用从网上下载的 HTML 和 JS 代码来录制音频 但有一个问题 因为页面加载到屏幕上后立即出现允许麦克风的消息 正是因为window onload function init 在源代码record js中 但我想在单击按钮后显示消息
  • 在控制台应用程序中捕获 ctrl+c 事件(多线程)

    我有一个控制台应用程序的主线程 它以这种方式运行很少的外部进程 private static MyExternalProcess p1 private static MyExternalProcess p2 private static M
  • 304 未修改问题

    抱歉 标题可能有误 我正在编写一些代码来处理 If Modified Since 和 If None Match 请求作为缓存的一部分 除了 PHP 在标头后面返回一些内容 空行 之外 一切都很完美 页面内容应该为空 我正在使用的代码是
  • 是否可以将别名模板标记为好友?

    想象一下我们有这样的代码 template
  • 在字符串文字中展开宏

    我想做的是 define一个宏 define a 2 然后在字符串文字中使用它 string a 我希望该字符串不被解释为字符串 而是获取值a 即2 我没有成功 有人可以帮忙吗 define STRINGIFY2 X X define ST
  • 参数作用域与局部变量作用域?

    我正在读我的 AP cs 书 它谈到了三种类型的变量 实例变量 局部变量 参数 实例变量在整个类中都是可见的等等 参数只能在方法内使用 局部变量也是如此 因此 我的问题是 如果参数和局部变量包含相同的范围 为什么他们会将参数和局部变量分类为
  • MySql 适合大型数据库吗? [关闭]

    Closed 这个问题需要细节或清晰度 help closed questions 目前不接受答案 我在一家公司工作 我们总是访问外部网站以获取信息 该网站是由一家过时的软件开发公司开发的 该公司甚至没有网站 他们在我所在的州几乎拥有垄断地
  • 如果 Blob URL 是不可变的,Media Source Extension API 如何使用它们来流式传输视频?

    让我们从一个例子开始 您访问 youtube com 该网站在某些设备上使用带有 HTML5 的媒体源扩展 MSE MSE 使用 blob URL 注入 标记 它看起来像这样 blob https www youtube com blahb
  • 了解 xargs 中的递归 grep

    以下两个命令之间有什么实际区别 命令A find type f print0 xargs 0 grep r masi 命令B find type f print0 xargs 0 grep masi 简而言之 命令 A 的实际好处是什么 N
  • 使用Python将文件加载到内存中

    我尝试使用以下命令将文件加载到内存中 import mmap with open path fileinput example txt rb as f fileinput mmap mmap f fileno 0 prot mmap PRO
  • Python Pandas 用户警告:由于非串联轴未对齐而进行排序

    我正在做一些代码练习并在执行此操作时应用数据帧合并 收到用户警告 usr lib64 python2 7 site packages pandas core frame py 6201 FutureWarning 由于非串联轴未对齐而进行排
  • python Flask如何将动态参数传递给装饰器

    我正在使用 python Flask 框架 我写了一个装饰器 它需要一个参数 并且这个参数将是动态的 我的装饰器如下所示 将获得一个密钥 并使用该密钥从 Redis 获取数据 def redis hash shop style key de
  • JOINed 表中的条件显示错误 CakePHP

    我有两张桌子employee personals存储员工的所有个人记录的地方telephone bills其中存储每月支付给特定员工的电话账单 现在在我的employeePersonalsController php我有一个函数叫做api
  • Excel、Vba 宏可将形状“移动”到不同的形状,无需复制和粘贴

    我想将形状移动到不同的工作表 而不在宏中使用复制和粘贴 还有其他方法可以做到这一点吗 如果形状是图表对象 您只需更改其位置即可 ActiveChart Location Where xlLocationAsObject Name Sheet
  • 我可以将编译的系统库(例如 libxml2)合并到可以部署到 Heroku 的 gem(例如 nokogiri)中吗?

    Nokogiri 在与 UTF 8 字符之间进行转换时遇到问题 结果发现该问题来自 libxml2 特别是版本 2 7 6 这是 Ubuntu 10 04 LTS 上支持的最高版本 该错误在 2 7 7 及更高版本中得到修复 但由于我们的应
  • 如何使用张量流和卷积神经网络检测和定位对象?

    我的问题陈述如下 使用 Tensorflow 和卷积神经网络进行对象检测和定位 我做了什么 我已经使用 tflearn 库完成了从图像中进行猫检测 我成功地使用 25000 张猫图像训练了一个模型 并且其工作良好且准确 Current Re
  • 日志记录挂钩的挂钩过程从未被调用

    我正在尝试创建一个简单的应用程序来记录和播放一系列键盘和鼠标命令 宏 阅读文档并得出结论 最合适的实现 如果不是唯一的实现 是设置 Windows 日志记录挂钩 WH JOURNALRECORD 并用日志回放一个 WH JOURNAL PL