玉兔远程控制 0.1.0-bate5
载入中...
搜索中...
未找到
HookWindows.cpp
1#include <QApplication>
2#include <QKeyEvent>
3#include <QLoggingCategory>
4#include <RabbitCommonTools.h>
5#include <QMessageBox>
6#include <QCheckBox>
7
8#include "FrmViewer.h"
9#include "HookWindows.h"
10#include "RabbitCommonTools.h"
11
12static Q_LOGGING_CATEGORY(log, "Client.Hook.Windows")
13
14CHookWindows::CHookWindows(CParameterPlugin *pParaClient, QObject *parent)
15 : CHook(pParaClient, parent),
16 m_hKeyboard(nullptr)
17{
18}
19
20CHookWindows::~CHookWindows()
21{
22 qDebug(log) << "CHookWindows::~CHookWindows()";
23}
24
25// See: https://docs.microsoft.com/en-us/previous-versions/windows/desktop/legacy/ms644985(v=vs.85)
26LRESULT CALLBACK CHookWindows::keyboardHookProc(INT code, WPARAM wparam, LPARAM lparam)
27{
28 if (code == HC_ACTION)
29 {
30 KBDLLHOOKSTRUCT* hook = reinterpret_cast<KBDLLHOOKSTRUCT*>(lparam);
31 /*
32 qDebug(log) << "process vkCode:" << hook->vkCode
33 << "scanCode:" << hook->scanCode
34 << "flags:" << hook->flags;//*/
35 int key = 0;
36 Qt::KeyboardModifiers keyMdf = Qt::NoModifier;
37 // See: [virtual-key-codes](https://learn.microsoft.com/zh-cn/windows/win32/inputdev/virtual-key-codes)
38 switch(hook->vkCode)
39 {
40 case VK_TAB:
41 {
42 key = Qt::Key_Tab;
43 break;
44 }
45 case VK_DELETE:
46 {
47 key = Qt::Key_Delete;
48 break;
49 }
50 case VK_LWIN:
51 {
52 key = Qt::Key_Super_L;
53 keyMdf = Qt::MetaModifier;
54 break;
55 }
56 case VK_RWIN:
57 {
58 key = Qt::Key_Super_R;
59 keyMdf = Qt::MetaModifier;
60 break;
61 }
62 case VK_MENU:
63 case VK_LMENU:
64 case VK_RMENU:
65 {
66 key = Qt::Key_Alt;
67 //keyMdf = Qt::KeyboardModifier::AltModifier;
68 break;
69 }
70 case VK_CONTROL:
71 case VK_LCONTROL:
72 case VK_RCONTROL:
73 {
74 key = Qt::Key_Control;
75 //keyMdf = Qt::KeyboardModifier::ControlModifier;
76 break;
77 }
78 case VK_SHIFT:
79 case VK_LSHIFT:
80 case VK_RSHIFT:
81 {
82 key = Qt::Key_Shift;
83 //keyMdf = Qt::KeyboardModifier::ShiftModifier;
84 break;
85 }
86 default:
87 break;
88 }
89 if(key) {
90 CFrmViewer* self = qobject_cast<CFrmViewer*>(QApplication::focusWidget());
91 WId foreground_window = reinterpret_cast<WId>(GetForegroundWindow());
92 if (self && self->parentWidget()->window()->winId() == foreground_window)
93 {
94 if(wparam == WM_KEYDOWN || wparam == WM_SYSKEYDOWN)
95 emit self->sigKeyPressEvent(new QKeyEvent(QKeyEvent::KeyPress, key, keyMdf));
96 //QApplication::postEvent(self, new QKeyEvent(QKeyEvent::KeyPress, key, keyMdf));
97 if(wparam == WM_KEYUP || wparam == WM_SYSKEYUP)
98 emit self->sigKeyReleaseEvent(new QKeyEvent(QKeyEvent::KeyRelease, key, Qt::NoModifier));
99 //QApplication::postEvent(self, new QKeyEvent(QKeyEvent::KeyRelease, key, Qt::NoModifier));
100 //*
101 qDebug(log) << "process vkCode:" << hook->vkCode
102 << "scanCode:" << hook->scanCode
103 << "flags:" << hook->flags;//*/
104 /* the hook procedure did not process the message,
105 * it is highly recommended that you call CallNextHookEx
106 * and return the value it returns; otherwise,
107 * other applications that have installed WH_KEYBOARD_LL hooks
108 * will not receive hook notifications and may behave incorrectly
109 * as a result. If the hook procedure processed the message,
110 * it may return a nonzero value to prevent the system
111 * from passing the message to the rest of the hook chain
112 * or the target window procedure.
113 */
114 return 1;
115 }
116 }
117 }
118
119 return CallNextHookEx(nullptr, code, wparam, lparam);
120}
121
122// See: https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-setwindowshookexw
123int CHookWindows::RegisterKeyboard()
124{
125 if(m_hKeyboard)
126 UnRegisterKeyboard();
127 DisableTaskManager(true);
128 m_hKeyboard = SetWindowsHookExW(WH_KEYBOARD_LL, keyboardHookProc, nullptr, 0);
129 if(NULL == m_hKeyboard) {
130 qCritical(log) << "SetWindowsHookExW error:" << GetLastError();
131 return -1;
132 }
133 return 0;
134}
135
136int CHookWindows::UnRegisterKeyboard()
137{
138 if(m_hKeyboard)
139 {
140 UnhookWindowsHookEx(m_hKeyboard);
141 m_hKeyboard = nullptr;
142 }
143 DisableTaskManager(false);
144 return 0;
145}
146
147// 启用备份和恢复权限
148bool EnableDebugPrivileges() {
149 HANDLE hToken = NULL;
150 LUID sedebugnameValue;
151 TOKEN_PRIVILEGES tkp;
152
153 // 获取当前进程的访问令牌
154 if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken)) {
155 qDebug(log) << "OpenProcessToken failed. Error:" << GetLastError();
156 return false;
157 }
158
159 do {
160 // 查找 SE_DEBUG_NAME 权限的LUID
161 if (!LookupPrivilegeValue(NULL, SE_RESTORE_NAME, &sedebugnameValue)) {
162 qDebug(log) << "LookupPrivilegeValue (SE_DEBUG_NAME) failed. Error:" << GetLastError();
163 break;
164 }
165
166 // 设置权限结构
167 tkp.PrivilegeCount = 1;
168 tkp.Privileges[0].Luid = sedebugnameValue;
169 tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
170
171 // 调整权限
172 if (!AdjustTokenPrivileges(hToken, FALSE, &tkp, sizeof(tkp), NULL, NULL)) {
173 qDebug(log) << "AdjustTokenPrivileges failed. Error:" << GetLastError();
174 break;
175 }
176
177 // 检查权限是否成功启用
178 if (GetLastError() == ERROR_NOT_ALL_ASSIGNED) {
179 qDebug(log) << "The token does not have the specified privileges.";
180 break;
181 }
182 qDebug(log) << "Debug privileges enabled successfully.";
183 }while(0);
184
185 CloseHandle(hToken);
186 return true;
187}
188
189//添加注册屏蔽 Ctrl+Alt+del
190//在注册表该目录下增加新内容
191#define TASKMANAGERSystem "HKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\CurrentVersion\\Policies\\System"
192#define TASKMANAGERExplorer "HKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\CurrentVersion\\Policies\\Explorer"
193void CHookWindows::DisableTaskManager(bool flag)
194{
195 // 屏蔽ctrl + alt +del 需要修改注册表的值, 取得管理员权限, 关闭360等杀毒软件
196 int value = flag ? 0x00000001 : 0x00000000;
197 QSettings settings(TASKMANAGERSystem, QSettings::NativeFormat);
198 settings.setValue("DisableTaskMgr", value); //任务管理器
199 settings.setValue("DisableChangePassword", value); //更改密码
200 settings.setValue("DisableLockWorkstation", value); //锁定计算机
201 settings.setValue("DisableSwitchUserOption", value); //切换用户
202
203 QSettings settings2(TASKMANAGERExplorer, QSettings::NativeFormat);
204 settings2.setValue("NoLogOff", value); //注销
205}
用于显示从 CConnectDesktop 输出的图像,和向 CConnectDesktop 发送键盘、鼠标事件。
Definition FrmViewer.h:48
The class is the HOOK abstract class.
Definition Hook.h:14
插件的全局参数。