windows防键盘监控

R3 应用层键盘监控主要分三种:

1、使用SetWindowsHookEx hook住WH_KEYBOARD_LL。

这种方式解决起来比较简单,就是不断hook与unhook,因为后hook的可以在先hook之前获取到通知,并选择是否传下去。

LRESULT CALLBACK LowLevelKeyboardProc(_In_ int nCode, _In_ WPARAM wParam, _In_ LPARAM lParam) {
  KBDLLHOOKSTRUCT *ks = (KBDLLHOOKSTRUCT*)lParam;

    /*typedef struct tagKBDLLHOOKSTRUCT {
      DWORD     vkCode;		// 按键代号
      DWORD     scanCode;		// 硬件扫描代号,同 vkCode 也可以作为按键的代号。
      DWORD     flags;		// 事件类型,一般按键按下为 0 抬起为 128。
      DWORD     time;			// 消息时间戳
      ULONG_PTR dwExtraInfo;	// 消息附加信息,一般为 0。
      }KBDLLHOOKSTRUCT,*LPKBDLLHOOKSTRUCT,*PKBDLLHOOKSTRUCT;*/

  //128keypress 129 keyrelease
  if (ks->flags == 128 || ks->flags == 129) {
    if (ks->vkCode > 0x2F && ks->vkCode < 0x70) {
      //0: 不传给下一个钩子 1:使按键无效
      return 0;
    }
  }
  //传给下个钩子
  return CallNextHookEx(NULL, nCode, wParam, lParam);
}


HookManager::HookManager(QObject* parent)
  :QObject(parent) {
  worker_ = new HookWorker;
  worker_->moveToThread(&work_thread_);
  connect(this, &HookManager::Work, worker_, &HookWorker::DoWork, Qt::QueuedConnection);
}

HookManager::~HookManager() {
  StopKook();

  if (worker_) {
    worker_->deleteLater();
    worker_ = nullptr;
  }
}

void HookManager::StartHook() {
  if (work_thread_.isRunning()) {
    return;
  }

  work_thread_.start();
  worker_->SetState(false);
  emit Work();
  return;
}

void HookManager::StopKook() {
  worker_->SetState(true);
  work_thread_.quit();
  work_thread_.wait();
}


HookWorker::HookWorker() {
  stop_ = false; 
}

HookWorker::~HookWorker() {
}

void HookWorker::DoWork() {
    MSG msg;
    QTime hook_time = QTime::currentTime();
    HHOOK hander = Hook();

    while (!stop_) {
      //处理消息,否则程序会卡死
      if (PeekMessageA(&msg, NULL, NULL, NULL, PM_REMOVE)) {
        // 把按键消息传递给字符消息
        TranslateMessage(&msg);
        // 将消息分派给窗口程序
        DispatchMessageW(&msg);
      }
      else {
        //避免CPU全负载运行
        QThread::msleep(1);
      }

      if (hook_time.msecsTo(QTime::currentTime()) >= 500) {
        hook_time = QTime::currentTime();
        UnHook(hander);
        hander = Hook();
      }
    }
}
HHOOK HookWorker::Hook() {
  // 钩子类型,WH_KEYBOARD_LL 为键盘钩子
  HHOOK keyboard_hook = SetWindowsHookEx(WH_KEYBOARD_LL,
    LowLevelKeyboardProc, GetModuleHandleA(NULL), NULL);// Dll 句柄

  if (keyboard_hook == 0) {
    LOG_WARN("挂钩键盘失败");
  }
  return keyboard_hook;
}
void HookWorker::UnHook(const HHOOK& hander) {
  UnhookWindowsHookEx(hander);
}

2、使用RawInputData 从输入设备获取数据

参考代码,目前的想法是,通过key_event发送部分假按键信号,在内存中维护真实的字符串,这样外部程序获取到的数据也是有真有假的。(QQ实现不是这样的,都是假的键盘输出,详情)

3、GetAsyncKeyState轮询键盘消息

  while (1) {
    short a = ::GetAsyncKeyState(VK_LSHIFT);
    if (0 != a) {
      printf("0x%x", a);
    }
      Sleep(10);
  }

未解决

要想彻底解决键盘监控需要在驱动层,利用IAT HOOK KeUserModeCallback的方法来防止消息钩子注入。

参考:键盘分析记录

RawInputData 参考代码

QQ实现防键盘监视

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值