繁体   English   中英

如何检测进程是否移动了鼠标 cursor 而不是用户?

[英]How to detect if a process has moved the mouse cursor and not the user?

It is possible to move the mouse calling the mouse_event function or by using System.Windows.Forms.Cursor.Position property. 我想知道的是,是否有可能知道使用我的软件的用户是否正在使用这些方法之一。

我知道可以检查用户的鼠标移动,例如,查看它是否发生得太快。 但我想知道是否还有其他更准确的方法,比如检查某个 WinApi function 是否被调用。

当鼠标被物理移动时,触发的是 mouse_event function 吗?

或者对 mouse_event function 的调用是否会进行另一个系统调用并调用“物理鼠标移动”使用的实际 function?

我不认为如果另一个进程通过代码更改了 cursor position 并且这不是移动它的用户是可能的,除非某些 WinAPI 可以通过代码移动它。

我测试过,如果代码更改 cursor position,则不会在 WinForm 上或使用全局挂钩引发 MouseMove。

因此,使用 GetLastInputInfo 不起作用,并且您似乎无法检测到进程是否更改了移动 position。

也就是说,您可以使用带有此 MouseMove 全局挂钩的计时器。

https://www.codeproject.com/Articles/7294/Processing-Global-Mouse-and-Keyboard-Hooks-in-C

  • 在应用程序启动时,您将像以前一样保存鼠标 position。

  • 例如,您启动一个间隔为 100 毫秒的计时器。

  • 在 MouseMove 上,您将更新之前的 position 并将条件变量设置为 true。

  • 在计时器滴答声中,您将获得当前的 position 并将其与先前的条件变量进行比较:如果不相同,则不是用户移动。

它很重,但有效。

如果用户在一个进程的同时移动鼠标,你只会得到移动的是用户。

使用 WinForms 计时器

public partial class FormTest : Form
{
  Point PreviousMousePosition;
  bool UserMovedMouse;
  public FormTest()
  {
    InitializeComponent();
    PreviousMousePosition = Cursor.Position;
    TimerCheckMouseMove.Start();
    TimerMoveMouse.Start();
    HookManager.MouseMove += HookManager_MouseMove;
  }
  private void HookManager_MouseMove(object sender, MouseEventArgs e)
  {
    PreviousMousePosition = Cursor.Position;
    UserMovedMouse = true;
  }
  private void TimerCheckMouseMove_Tick(object sender, EventArgs e)
  {
    TimerCheckMouseMove.Enabled = false;
    try
    {
      var pos = Cursor.Position;
      if ( !UserMovedMouse && pos != PreviousMousePosition)
        MessageBox.Show("Mouse moved by a process");
      PreviousMousePosition = Cursor.Position;
      UserMovedMouse = false;
    }
    finally
    {
      TimerCheckMouseMove.Enabled = true;
    }
  }
  private void TimerMoveMouse_Tick(object sender, EventArgs e)
  {
    Cursor.Position = new Point(100, 100);
  }
}

使用线程计时器

System.Threading.Timer TimerCheckMouseMove;

TimerCheckMouseMove = new System.Threading.Timer(TimerCheckMouseMove_Tick, null, 0, 100);

private bool TimerCheckMouseMoveMutex;

private void TimerCheckMouseMove_Tick(object state)
{
  if ( TimerCheckMouseMoveMutex ) return;
  TimerCheckMouseMoveMutex = true;
  try
  {
    var pos = Cursor.Position;
    if ( !UserMovedMouse && pos != PreviousMousePosition)
      MessageBox.Show("Mouse moved by a process");
    PreviousMousePosition = Cursor.Position;
    UserMovedMouse = false;
  }
  finally
  {
    TimerCheckMouseMoveMutex = false;
  }
}

可以使用 API 调用SendInput()mouse_event()来检测鼠标输入是否由代码生成。 为此,请使用SetWindowsHookEx()设置低级鼠标挂钩 这个钩子过程被传递了一个MSLLHOOKSTRUCT ,其flags成员指示鼠标事件是由代码注入的结果,还是用户输入的结果。

如果攻击者正在向您的应用程序发送鼠标消息,您可以从鼠标消息处理程序中调用InSendMessage 真正的鼠标消息发布到消息队列。 通常会发送假鼠标消息。 如果InSendMessage返回TRUE ,您可以确定收到了虚假的输入消息。 如果攻击者确实发布了消息,您将不得不依靠识别实际输入设备 state 和预期的 state 之间的不匹配。 GetKeyState可用于此。

没有直接的方法来检测对SetCursorPos的调用。 单独来看,这些调用不会生成用户输入,也不能用于自动化应用程序。 它们总是伴随着其他注入输入的方案,你知道如何识别它们。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM