玉兔远程控制 0.1.0-bate5
载入中...
搜索中...
未找到
HookWindows.cpp
1// Author: Kang Lin <kl222@126.com>
2
3#include <QApplication>
4#include <QKeyEvent>
5#include <QLoggingCategory>
6#include <RabbitCommonTools.h>
7#include <QMessageBox>
8#include <QCheckBox>
9
10#include "FrmViewer.h"
11#include "HookWindows.h"
12#include "RabbitCommonTools.h"
13
14static Q_LOGGING_CATEGORY(log, "Plugin.Hook.Windows")
15
16CHookWindows::CHookWindows(CParameterPlugin *pParaClient, QObject *parent)
17 : CHook(pParaClient, parent),
18 m_hKeyboard(nullptr)
19{
20}
21
22CHookWindows::~CHookWindows()
23{
24 qDebug(log) << "CHookWindows::~CHookWindows()";
25}
26
27// See: https://docs.microsoft.com/en-us/previous-versions/windows/desktop/legacy/ms644985(v=vs.85)
28LRESULT CALLBACK CHookWindows::keyboardHookProc(INT code, WPARAM wparam, LPARAM lparam)
29{
30 if (code == HC_ACTION)
31 {
32 KBDLLHOOKSTRUCT* hook = reinterpret_cast<KBDLLHOOKSTRUCT*>(lparam);
33 /*
34 qDebug(log) << "process vkCode:" << hook->vkCode
35 << "scanCode:" << hook->scanCode
36 << "flags:" << hook->flags;//*/
37 int key = 0;
38 Qt::KeyboardModifiers keyMdf = Qt::NoModifier;
39 // See: [virtual-key-codes](https://learn.microsoft.com/zh-cn/windows/win32/inputdev/virtual-key-codes)
40 switch(hook->vkCode)
41 {
42 case VK_TAB:
43 {
44 key = Qt::Key_Tab;
45 break;
46 }
47 case VK_DELETE:
48 {
49 key = Qt::Key_Delete;
50 break;
51 }
52 case VK_LWIN:
53 {
54 key = Qt::Key_Super_L;
55 keyMdf = Qt::MetaModifier;
56 break;
57 }
58 case VK_RWIN:
59 {
60 key = Qt::Key_Super_R;
61 keyMdf = Qt::MetaModifier;
62 break;
63 }
64 case VK_MENU:
65 case VK_LMENU:
66 case VK_RMENU:
67 {
68 key = Qt::Key_Alt;
69 //keyMdf = Qt::KeyboardModifier::AltModifier;
70 break;
71 }
72 case VK_CONTROL:
73 case VK_LCONTROL:
74 case VK_RCONTROL:
75 {
76 key = Qt::Key_Control;
77 //keyMdf = Qt::KeyboardModifier::ControlModifier;
78 break;
79 }
80 case VK_SHIFT:
81 case VK_LSHIFT:
82 case VK_RSHIFT:
83 {
84 key = Qt::Key_Shift;
85 //keyMdf = Qt::KeyboardModifier::ShiftModifier;
86 break;
87 }
88 default:
89 break;
90 }
91 if(key) {
92 CFrmViewer* self = qobject_cast<CFrmViewer*>(QApplication::focusWidget());
93 WId foreground_window = reinterpret_cast<WId>(GetForegroundWindow());
94 if (self && self->parentWidget()->window()->winId() == foreground_window)
95 {
96 if(wparam == WM_KEYDOWN || wparam == WM_SYSKEYDOWN)
97 emit self->sigKeyPressEvent(new QKeyEvent(QKeyEvent::KeyPress, key, keyMdf));
98 //QApplication::postEvent(self, new QKeyEvent(QKeyEvent::KeyPress, key, keyMdf));
99 if(wparam == WM_KEYUP || wparam == WM_SYSKEYUP)
100 emit self->sigKeyReleaseEvent(new QKeyEvent(QKeyEvent::KeyRelease, key, Qt::NoModifier));
101 //QApplication::postEvent(self, new QKeyEvent(QKeyEvent::KeyRelease, key, Qt::NoModifier));
102 //*
103 qDebug(log) << "process vkCode:" << hook->vkCode
104 << "scanCode:" << hook->scanCode
105 << "flags:" << hook->flags;//*/
106 /* the hook procedure did not process the message,
107 * it is highly recommended that you call CallNextHookEx
108 * and return the value it returns; otherwise,
109 * other applications that have installed WH_KEYBOARD_LL hooks
110 * will not receive hook notifications and may behave incorrectly
111 * as a result. If the hook procedure processed the message,
112 * it may return a nonzero value to prevent the system
113 * from passing the message to the rest of the hook chain
114 * or the target window procedure.
115 */
116 return 1;
117 }
118 }
119 }
120
121 return CallNextHookEx(nullptr, code, wparam, lparam);
122}
123
124// See: https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-setwindowshookexw
125int CHookWindows::OnRegisterKeyboard()
126{
127 if(m_hKeyboard)
128 UnRegisterKeyboard();
129 m_hKeyboard = SetWindowsHookExW(WH_KEYBOARD_LL, keyboardHookProc, nullptr, 0);
130 if(NULL == m_hKeyboard) {
131 qCritical(log) << "SetWindowsHookExW error:" << GetLastError();
132 return -1;
133 }
134 return 0;
135}
136
137int CHookWindows::OnUnRegisterKeyboard()
138{
139 if(m_hKeyboard)
140 {
141 UnhookWindowsHookEx(m_hKeyboard);
142 m_hKeyboard = nullptr;
143 }
144 return 0;
145}
146
147int CHookWindows::OnDisableDesktopShortcuts()
148{
149 DisableTaskManager(true);
150 return 0;
151}
152
153int CHookWindows::OnRestoreDesktopShortcuts()
154{
155 DisableTaskManager(false);
156 return 0;
157}
158
159// 启用备份和恢复权限
160bool EnableDebugPrivileges() {
161 HANDLE hToken = NULL;
162 LUID sedebugnameValue;
163 TOKEN_PRIVILEGES tkp;
164
165 // 获取当前进程的访问令牌
166 if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken)) {
167 qDebug(log) << "OpenProcessToken failed. Error:" << GetLastError();
168 return false;
169 }
170
171 do {
172 // 查找 SE_DEBUG_NAME 权限的LUID
173 if (!LookupPrivilegeValue(NULL, SE_RESTORE_NAME, &sedebugnameValue)) {
174 qDebug(log) << "LookupPrivilegeValue (SE_DEBUG_NAME) failed. Error:" << GetLastError();
175 break;
176 }
177
178 // 设置权限结构
179 tkp.PrivilegeCount = 1;
180 tkp.Privileges[0].Luid = sedebugnameValue;
181 tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
182
183 // 调整权限
184 if (!AdjustTokenPrivileges(hToken, FALSE, &tkp, sizeof(tkp), NULL, NULL)) {
185 qDebug(log) << "AdjustTokenPrivileges failed. Error:" << GetLastError();
186 break;
187 }
188
189 // 检查权限是否成功启用
190 if (GetLastError() == ERROR_NOT_ALL_ASSIGNED) {
191 qDebug(log) << "The token does not have the specified privileges.";
192 break;
193 }
194 qDebug(log) << "Debug privileges enabled successfully.";
195 }while(0);
196
197 CloseHandle(hToken);
198 return true;
199}
200
201//添加注册屏蔽 Ctrl+Alt+del
202//在注册表该目录下增加新内容
203#define TASKMANAGERSystem "HKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\CurrentVersion\\Policies\\System"
204#define TASKMANAGERExplorer "HKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\CurrentVersion\\Policies\\Explorer"
205#define WINLOGON "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon"
206void CHookWindows::DisableTaskManager(bool flag)
207{
208 // 屏蔽ctrl + alt +del 需要修改注册表的值, 取得管理员权限, 关闭360等杀毒软件
209 int value = flag ? 0x00000001 : 0x00000000;
210 QSettings system(TASKMANAGERSystem, QSettings::NativeFormat);
211 system.setValue("DisableTaskMgr", value); //任务管理器
212 system.setValue("DisableChangePassword", value); //更改密码
213 system.setValue("DisableSwitchUserOption", value); //切换用户
214 system.setValue("DisableCAD", value); // Disable ctrl+alt+del
215 system.setValue("DisableLockWorkstation", value); //锁定计算机
216
217 QSettings explorer(TASKMANAGERExplorer, QSettings::NativeFormat);
218 explorer.setValue("NoLogOff", value); //注销
219
220 /*
221 QSettings winlogon(WINLOGON, QSettings::NativeFormat);
222 winlogon.setValue("DisableCAD", value); // Disable ctrl+alt+del
223 winlogon.setValue("DisableLockWorkstation", value); //锁定计算机
224 //*/
225}
226
227bool CHookWindows::DisableWindowsKey()
228{
229 // 方法1: 使用 RegisterHotKey 来占用 Windows 键
230 bool success = true;
231
232 // 注册热键来拦截 Windows 键
233 if (!RegisterHotKey(nullptr, 1, MOD_WIN, VK_LWIN)) {
234 qCritical(log) << "注册左 Windows 键拦截失败:" << GetLastError();
235 success = false;
236 }
237
238 if (!RegisterHotKey(nullptr, 2, MOD_WIN, VK_RWIN)) {
239 qCritical(log) << "注册右 Windows 键拦截失败:" << GetLastError();
240 success = false;
241 }
242
243 // 方法2: 修改注册表禁用 Windows 键
244 HKEY hKey;
245 LONG result = RegCreateKeyExW(HKEY_CURRENT_USER,
246 L"Software\\Microsoft\\Windows\\CurrentVersion\\Policies\\Explorer",
247 0, nullptr, 0, KEY_ALL_ACCESS, nullptr, &hKey, nullptr);
248
249 if (result == ERROR_SUCCESS) {
250 DWORD value = 1; // 1 表示禁用 Windows 键
251 result = RegSetValueExW(hKey, L"NoWinKeys", 0, REG_DWORD,
252 reinterpret_cast<const BYTE*>(&value), sizeof(value));
253
254 if (result == ERROR_SUCCESS) {
255 qDebug(log) << "注册表设置成功,Windows 键已禁用";
256 } else {
257 qWarning(log) << "注册表设置失败:" << result;
258 success = false;
259 }
260 RegCloseKey(hKey);
261 } else {
262 qWarning(log) << "创建注册表键失败:" << result;
263 success = false;
264 }
265
266 return success;
267}
268
269bool CHookWindows::EnableWindowsKey()
270{
271 bool success = true;
272
273 // 取消注册热键
274 UnregisterHotKey(nullptr, 1);
275 UnregisterHotKey(nullptr, 2);
276
277 // 恢复注册表设置
278 HKEY hKey;
279 LONG result = RegOpenKeyExW(HKEY_CURRENT_USER,
280 L"Software\\Microsoft\\Windows\\CurrentVersion\\Policies\\Explorer",
281 0, KEY_ALL_ACCESS, &hKey);
282
283 if (result == ERROR_SUCCESS) {
284 result = RegDeleteValueW(hKey, L"NoWinKeys");
285 if (result == ERROR_SUCCESS || result == ERROR_FILE_NOT_FOUND) {
286 qDebug(log) << "Windows 键已恢复";
287 } else {
288 qWarning(log) << "删除注册表值失败:" << result;
289 success = false;
290 }
291 RegCloseKey(hKey);
292 }
293
294 return success;
295}
296
297bool CHookWindows::DisableTaskManager()
298{
299 bool bRet = false;
300 HKEY hKey;
301 LONG result = RegCreateKeyExW(HKEY_CURRENT_USER,
302 L"Software\\Microsoft\\Windows\\CurrentVersion\\Policies\\System",
303 0, nullptr, 0, KEY_ALL_ACCESS, nullptr, &hKey, nullptr);
304
305 if (result == ERROR_SUCCESS) {
306 DWORD value = 1; // 1 表示禁用任务管理器
307 result = RegSetValueExW(hKey, L"DisableTaskMgr", 0, REG_DWORD,
308 reinterpret_cast<const BYTE*>(&value), sizeof(value));
309
310 if (result == ERROR_SUCCESS) {
311 qDebug(log) << "任务管理器已禁用";
312 bRet = true;
313 } else {
314 qWarning(log) << "禁用任务管理器失败:" << result;
315 }
316 RegCloseKey(hKey);
317 }
318
319 return bRet;
320}
321
322bool CHookWindows::EnableTaskManager()
323{
324 HKEY hKey;
325 LONG result = RegOpenKeyExW(HKEY_CURRENT_USER,
326 L"Software\\Microsoft\\Windows\\CurrentVersion\\Policies\\System",
327 0, KEY_ALL_ACCESS, &hKey);
328
329 if (result == ERROR_SUCCESS) {
330 result = RegDeleteValueW(hKey, L"DisableTaskMgr");
331 RegCloseKey(hKey);
332
333 if (result == ERROR_SUCCESS || result == ERROR_FILE_NOT_FOUND) {
334 qDebug(log) << "任务管理器已恢复";
335 return true;
336 }
337 }
338
339 return false;
340}
341
用于显示从 CConnectDesktop 输出的图像,和向 CConnectDesktop 发送键盘、鼠标事件。
Definition FrmViewer.h:48
The class is the HOOK abstract class.
Definition Hook.h:15
插件的全局参数。