3

It is possible to move the mouse calling the mouse_event function or by using System.Windows.Forms.Cursor.Position property. What I want to know is, if it's possible to know if a user using my software is using one of these methods or not.

I know it is possible to check the users mouse movement and, for example, see if it happened too quick or not. But I'm wondering if there are other more accurate ways, like checking if a certain WinApi function is being called or not.

When a mouse is moved physically, is it mouse_event function that gets triggered?

Or does the call to the mouse_event function makes another system call and calls the actual function the 'physical mouse move' uses?

CanBerk
  • 93
  • 6
  • 1
    Welcome to StackOverflow. Thank you for taking the time to share your problem. What you asking for is unclear. What is your goal and your difficulty? What have you done so far? Please try to better explain your issue, your development environment and the data structures, as well as to share more code (no screenshot), images or sketches of the screen, and user stories or scenario diagrams. To help you improve your requests, please read the *[How do I ask a good question](https://stackoverflow.com/help/how-to-ask)* and **Questions I avoid asking** at the top right. –  Nov 09 '19 at 05:55
  • @OlivierRogier Hello! Thanks for the feedback. I will try to make the question clearer by editing it. I've read the link you posted and the part that says "Not all questions benefit from including code." applies to my question as well. – CanBerk Nov 09 '19 at 06:00
  • I don't understand the question. All the text and especially *if it's possible to know if a user is using one of these methods or not*. Do you want to know how to move the cursor, how to detect if the cursor is moved, or if another processus do something about that... Clarifying the question and adding code or diagram may help to see what you try to do. –  Nov 09 '19 at 06:03
  • @OlivierRogier I tried to ask in a different way with my edit. I have no code to show since I'm trying to learn if this is even possible or not. I'm expecting an answer like "it's not possible, the physical mouse move calls the same function that a user can call in his code" or an answer like "it's possible, look into process handles and see what they point to". – CanBerk Nov 09 '19 at 06:07
  • A user is the person that uses the app. He interacts with it. He don't call any code himself. –  Nov 09 '19 at 06:08
  • Those functions just insert events into the mouse input stream; they're not any different than events from the actual mouse. – Herohtar Nov 09 '19 at 06:11
  • 1
    Related: https://stackoverflow.com/questions/37411535/detect-if-keyboard-or-mouse-events-are-triggered-by-a-software – Herohtar Nov 09 '19 at 06:12
  • @OlivierRogier I think you are right, sorry. I'll ask a native speaker for help and ask this again since I can't actually structure this question better. So the question is, I have a software people use. Mouse movement is important in the software. I don't want anyone to "cheat" by writing scripts to automate or gain advantage over others. So I'm trying to detect if a mouse movement is "real" or from calling one of the functions mentioned. – CanBerk Nov 09 '19 at 06:12
  • @Herohtar Yes, thank you! The word I was looking for was "emulated". Not coming up with it failed me with my Goggle searches, much appreciated for the link! – CanBerk Nov 09 '19 at 06:13
  • @OlivierRogier Thank you very much, this was exactly the answer I was looking for. Now that I know some more keywords I'll keep researching, but your answer seems to be the consensus... – CanBerk Nov 09 '19 at 06:31
  • @urgent2009 Answer updated: now it can work. –  Nov 09 '19 at 08:09

2 Answers2

0

I don't think that be warned if another process changed the cursor position by code and that is not the user that moved it is possible unless some WinAPI to move it by code has an event that can be registered.

I tested that if a code change the cursor position, no MouseMove is raised on a WinForm or by using a global hook.

So using GetLastInputInfo does not work and it seems that you can't detect if a process has changed the move position.

That said, you can use a timer with this MouseMove global hook.

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

  • On app start you will save the mouse position as previous.

  • You start a timer having interval 100ms for example.

  • On MouseMove you will update this previous position and set a conditional variable to true.

  • On the timer tick, you will get the current position and compare it to previous and the conditional variable: if it is not the same, it is not the user that moves.

It is heavy but that works.

If the user moves the mouse same time a process, you will only get that it is the user that moves.

Using a WinForms Timer

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);
  }
}

Using a threaded timer

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;
  }
}
  • This is ignoring, how `WM_MOUSEMOVE` messages really work: [Why do I get spurious WM_MOUSEMOVE messages?](https://devblogs.microsoft.com/oldnewthing/?p=42343). – IInspectable Nov 10 '19 at 07:22
0

It is possible to detect whether mouse input was generated by code using the API calls SendInput() or mouse_event(). To do so, use SetWindowsHookEx() to set up a low-level mouse hook. This hook procedure is passed a MSLLHOOKSTRUCT whose flags member indicates whether mouse events were the result of being injected by code, or the result of user input.

In case an attacker is sending mouse messages to your application, you can call InSendMessage from your mouse message handlers. Genuine mouse messages are posted to the message queue. Fake mouse messages are usually sent. If InSendMessage returns TRUE you can be sure to have gotten a fake input message. If the attacker does indeed post messages, you'll have to rely on identifying mismatches between the actual input device state and the expected state. GetKeyState can be used for this.

There's no immediate way to detect calls to SetCursorPos. In isolation, those calls do not generate user input, and cannot be used to automate an application. They are always accompanied by other schemes to inject input, and you know how to identify those.

IInspectable
  • 46,945
  • 8
  • 85
  • 181
  • Can that be able to detect a mouse move by code and not by user? How it works? –  Nov 09 '19 at 12:19
  • 1
    https://stackoverflow.com/questions/45008637/how-to-detect-if-keystroke-was-emulated-by-keybd-event-or-sendinput - this link mentions that " The hook doesn't even know which app will actually receive the keys, since the hook is invoked after the keystrokes are removed from the hardware queue and before the OS determines the receiving app" so what you say might not be possible. – CanBerk Nov 09 '19 at 14:40
  • 1
    My answer is echoing official documentation. If you have reason to believe that what the API documentation promises and what the API delivers are not the same thing, file a documentation defect issue. More probably however is that what you asked for and the problem you need to solve are not the same thing. I answered the question you asked. – IInspectable Nov 09 '19 at 17:00
  • @IInspectable on the other hand, a low-level mouse hook only detects events that go through the hardware queue, even injected ones, but it doesn't detect things like `SetCursorPos()` which don't go through the hardware queue – Remy Lebeau Nov 09 '19 at 19:44
  • @rem: `SetCursorPos` does not strictly generate user input. By itself, it cannot be used to automate an application. It will always need brothers in crime, and those can be identified. – IInspectable Nov 10 '19 at 07:16