繁体   English   中英

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

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

我创建了一个简单的机器人来自动化游戏中的某些东西。 我目前通过将游戏窗口带到前台并使用SendKeys发送密钥来向游戏发送命令,如下所示:

SendKeys.Send("{ENTER}")

我想知道的是,从可检测性的角度来看,如果反作弊引擎更容易检测到这样的事情(使用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);

最后,游戏会收到输入键的keydown事件,对吧?

  • SendKeys.Send通常使用SendInput 基于日志挂钩的替代方法对于UAC是不可行的,因此我们假设SendKeys.Send解析为SendInput
  • SendMessage以同步方式将消息直接传递给窗口过程。

所以,这更容易检测。 好吧,肯定答案是SendMessage 这些是到达窗口过程的输入消息,而没有通过调用GetMessage从队列中取出。 这很容易被发现。 您只需记录有关从队列中提取的最新消息的一些信息,并在窗口过程中,根据最新排队的消息检查消息。

现在,区分SendInput和真实的人类输入可能比那更难。 我很确定它有可能。 一种方法是安装低级键盘钩子并查找LLKHF_INJECTED标志。 更难,但不是那么难。

这是一个概念性问题,也是技术问题。

  • SendKeys.Send() - 是WinAPI SendInput()函数的Windows窗体包装器。 此功能直接用于鼠标和键盘输入流。 虽然有一些限制(请阅读相关文档)。

  • SendMessage() - 是一个WinAPI函数。 它用于将特定消息发送到窗口。 除鼠标或键盘输入外,它还可用于发送其他消息。 这是一种更高级别的消息传递队列,其中许多其他消息被聚合,以发送到窗口。 在进程之间编组消息也存在限制。

  • 可检测性 :这实际上取决于你可以模仿按下按钮的过程有多好,以及你所反对的反作弊引擎有多好。 当人按下按钮时,几乎没有其他消息被发送到窗口。 除WM_KEYDOWN外,还有WM_KEYUP和其他一些。 您的任务是尽可能地重新创建该序列。 您将不得不对此主题进行自己的研究。 您已经可以看到人类按下按钮,不可能创建只向窗口发送WM_KEYDOWN的情况, WM_KEYUP必须跟进。 两者之间的延迟应该是人类可能的等等......

我也相信,SendMessage()可能无法正常运行游戏,因为他们中的许多人使用DirectX DirectInput,在这种情况下,我认为WinAPI SendInput()函数可以做得更好,因为它是一个较低级别的API并且可以工作直接与输入流。

暂无
暂无

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

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