Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Sending keystrokes to an application, SendKeys.Send() vs SendMessage()

Tags:

c#

winforms

I have created a simple bot to automate some things in a game. I'm currently sendings commands to the game by bringing the game window to the foreground and sending keys using SendKeys, like this:

SendKeys.Send("{ENTER}")

What I would like to know is, from a detectability point of view, if it's easier for anti cheat engines and such to detect something like this (using SendMessage):

public static void SendKeystroke(ushort k)
{
    const uint WM_KEYDOWN = 0x100;
    const uint WM_SYSCOMMAND = 0x018;
    const uint SC_CLOSE = 0x053;

    IntPtr WindowToFind = FindWindow(null, "Untitled1 - Notepad++");

    IntPtr result3 = SendMessage(WindowToFind, WM_KEYDOWN, 
                                    ((IntPtr)k), (IntPtr)0);
}

SendKeystroke(Keys.Enter);

In the end, the game would receive a keydown event for the enter key nontheless, right?

like image 951
Johan Avatar asked Dec 06 '13 12:12

Johan


2 Answers

  • SendKeys.Send typically uses SendInput. The alternative method based on journal hooks is not viable with UAC so let us assume that SendKeys.Send resolves to SendInput.
  • SendMessage delivers messages direct to the window proc in a synchronous manner.

So, which is easier to detect. Well, for sure the answer is SendMessage. These are input messages that arrive at the window procedure without ever having been pulled off the queue with a call to GetMessage. That is trivially easy to detect. You simply log some information about the latest message pulled from the queue, and in the window procedure, check the message against the latest queued message.

Now, discriminating between SendInput and real human input is probably harder than that. I'm quite sure it's possible though. One way is to install a low-level keyboard hook and look for the LLKHF_INJECTED flag. Harder, but not that much harder.

like image 177
David Heffernan Avatar answered Oct 21 '22 12:10

David Heffernan


This is a conceptual question as well as technical.

  • SendKeys.Send() - is a Windows Forms wrapper for the WinAPI SendInput() function. This function works directly with mouse and keyboard input stream. Though there are some limitations(please, read the documentation for this).

  • SendMessage() - is a WinAPI function. It is used to send a specific message to a window(s). It can be used to send other messages besides mouse or keyboard input. This is sort of a higher level messaging queue where many other messages get aggregated, to be sent to the window(s). There are also limitations on marshaling messages between processes.

  • Detectability: this will really depend on how good you can mimic the process of pressing a button and how good the anti-cheat engine is that you are up against. When a human presses a button there is few other messages are send to the window. Besides WM_KEYDOWN, there is WM_KEYUP and some other. Your task is to re-create that sequence as close as possible. You will have to do your own research on this topic. You already can see that human, pressing a button, can not possibly create a situation where only WM_KEYDOWN is sent to the window, WM_KEYUP must follow up. Also the delay between the two should be humanly possible and so on...

I also believe, SendMessage() may not work as expected with games, because many of them use DirectX DirectInput and in this case the WinAPI SendInput() function, I think, can do a better job as it is a lower level API and works directly with the input stream.

like image 45
Andrei Avatar answered Oct 21 '22 12:10

Andrei