简体   繁体   English

向应用程序发送击键,SendKeys.Send()vs SendMessage()

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

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发送密钥来向游戏发送命令,如下所示:

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 ): 我想知道的是,从可检测性的角度来看,如果反作弊引擎更容易检测到这样的事情(使用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? 最后,游戏会收到输入键的keydown事件,对吧?

  • SendKeys.Send typically uses SendInput . SendKeys.Send通常使用SendInput The alternative method based on journal hooks is not viable with UAC so let us assume that SendKeys.Send resolves to SendInput . 基于日志挂钩的替代方法对于UAC是不可行的,因此我们假设SendKeys.Send解析为SendInput
  • SendMessage delivers messages direct to the window proc in a synchronous manner. SendMessage以同步方式将消息直接传递给窗口过程。

So, which is easier to detect. 所以,这更容易检测。 Well, for sure the answer is SendMessage . 好吧,肯定答案是SendMessage These are input messages that arrive at the window procedure without ever having been pulled off the queue with a call to GetMessage . 这些是到达窗口过程的输入消息,而没有通过调用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. 现在,区分SendInput和真实的人类输入可能比那更难。 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. 一种方法是安装低级键盘钩子并查找LLKHF_INJECTED标志。 Harder, but not that much harder. 更难,但不是那么难。

This is a conceptual question as well as technical. 这是一个概念性问题,也是技术问题。

  • SendKeys.Send() - is a Windows Forms wrapper for the WinAPI SendInput() function. SendKeys.Send() - 是WinAPI SendInput()函数的Windows窗体包装器。 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. SendMessage() - 是一个WinAPI函数。 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. 除WM_KEYDOWN外,还有WM_KEYUP和其他一些。 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. 您已经可以看到人类按下按钮,不可能创建只向窗口发送WM_KEYDOWN的情况, WM_KEYUP必须跟进。 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. 我也相信,SendMessage()可能无法正常运行游戏,因为他们中的许多人使用DirectX DirectInput,在这种情况下,我认为WinAPI SendInput()函数可以做得更好,因为它是一个较低级别的API并且可以工作直接与输入流。

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

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