【甜点】脚本外挂的检测及预防

作者:amnesiac 首发:官方论坛中文版
导言:一些游戏在运行时能检测并屏蔽脚本外挂,原理是什么?有什么办法可以知道当前系统中开了多少脚本?包括使用默认托盘图标、自定义图标甚至隐藏了托盘图标的脚本。还有,能发现已编译成可执行文件的脚本吗?是否能控制这些脚本??

检测在运行的脚本

获取系统中当前运行的所有 AutoHotkey 脚本的信息(下面的脚本获取脚本标题和进程路径):

DetectHiddenWindows, on
WinGet, AHKWinList, List, ahk_class AutoHotkey 
Loop, %AHKWinList%
{
  AHKWinHWND := AHKWinList%A_Index%
  WinGetTitle, AHKWinTitle, ahk_id %AHKWinHWND%
  WinGet, AHKWinProcessPath, ProcessPath, ahk_id %AHKWinHWND%
  MsgBox, % "脚本标题:" AHKWinTitle "`n脚本进程路径:" AHKWinProcessPath
}
return

由于可以获取到窗口句柄,所以可以直接通过窗口命令获取指定脚本的各种信息。其中脚本标题中包含了脚本文件名和执行脚本的 AutoHotkey.exe 版本号,例如:

D:\Software\AutoHotkey\Scripts\test.ahk - AutoHotkey v1.1.15.00

当然,还可以使用其他方法。下面通过消息获取某脚本的进程 ID:

AHKScriptName := "MyScript.ahk"
SetTitleMatchMode, 2
DetectHiddenWindows, on
SendMessage, 0x44, 0x405, 0, , %AHKScriptName% ahk_class AutoHotkey
MsgBox %ErrorLevel% is the process id.

想判断哪些是未编译脚本, 哪些是已编译脚本, 请看下图:


运行的 AutoHotkey 脚本列表
运行的 AutoHotkey 脚本列表

图中显示当前系统运行了两个 AutoHotkey 脚本,我们对比这两个脚本的窗口名称:

  • D:\Software\AutoHotkey\Scripts\test.ahk - AutoHotkey v1.1.15.00
  • D:\Software\AutoHotkey\Scripts\test.exe

可以看出一个是未编译脚本,一个是已编译脚本,因此可以根据窗口名判断(其他信息也有差异)。注:从我使用这种方法开始到现在,窗口名称的规律没有发生变化,不过这里无法保证以后的所有版本都会遵从。

对这些脚本进行控制

在写脚本时,我们都知道可以很方便的对当前脚本进行控制,如:

Pause::Pause
^!s::Suspend
^!r::Reload
^+q::ExitApp
!l::ListLines
!v::ListVars
!k::KeyHistory

提示:我以前写脚本时习惯加上许多这样的热键,包括暂停、重启、列出热键、列出执行行、列出变量、显示按键历史等,调试时很方便。那么,对其他脚本我们可以实现这些功能吗?

AHKScriptName := "MyScript.ahk"
DetectHiddenWindows On  ; 才可以检测到脚本的隐藏主窗口.
SetTitleMatchMode 2  ; 避免为下面的文件指定完整的路径.
WM_COMMAND := 0x111
ID_FILE_PAUSE := 65403
ID_FILE_SUSPEND := 65404
PostMessage, WM_COMMAND, ID_FILE_PAUSE,,, %AHKScriptName% ahk_class AutoHotkey
PostMessage, WM_COMMAND, ID_FILE_SUSPEND,,, %AHKScriptName% ahk_class AutoHotkey
WinClose, %AHKScriptName% ahk_class AutoHotkey ; 关闭脚本,也可以使用消息,不过这里使用窗口命令可能直观一些。
; 下面两个同样是挂起和暂停的功能
PostMessage, 0x111, 65305,,, %AHKScriptName% ahk_class AutoHotkey ; 挂起
PostMessage, 0x111, 65306,,, %AHKScriptName% ahk_class AutoHotkey ; 暂停

注意:当前我不清楚如何判断脚本当前处于哪种状态(当前脚本可使用 A_IsSuspended、A_IsPaused)。

还有哪些可用的消息?我提供几点思路供参考:

  • 执行操作时通过工具截取消息(消息很多,这些属于 WM_COMMAND)
  • 直接到官方论坛询问作者

我比较懒,下面是通过源代码提取的一些消息号(可能不完整,前面部分是消息号分配的说明):

0: unused (possibly special in some contexts)
1: IDOK
2: IDCANCEL
3 to 1002: GUI window control IDs (these IDs must be unique only within their parent, not across all GUI windows)
1003 to 65299: User Defined Menu IDs
65300 to 65399: Standard tray menu items.
65400 to 65534: main menu items

消息号 含义
65300 ID_TRAY_OPEN
65400 ID_FILE_RELOADSCRIPT, ID_TRAY_RELOADSCRIPT
65401 ID_FILE_EDITSCRIPT, ID_TRAY_EDITSCRIPT
65402 ID_FILE_WINDOWSPY, ID_TRAY_WINDOWSPY
65403 ID_FILE_PAUSE, ID_TRAY_PAUSE
65404 ID_FILE_SUSPEND, ID_TRAY_SUSPEND
65405 ID_FILE_EXIT, ID_TRAY_EXIT
65406 ID_VIEW_LINES
65407 ID_VIEW_VARIABLES
65408 ID_VIEW_HOTKEYS
65409 ID_VIEW_KEYHISTORY
65410 ID_VIEW_REFRESH
65411 ID_HELP_USERMANUAL, ID_TRAY_HELP
65412 ID_HELP_WEBSITE

注:一般而言在更新版本时消息号的用途不太可能发生变化,不过为了安全,在使用前最好明确其用途,否则可能发生意外情况。

实现的具体原理

在前面的脚本中我们应该注意到两点:

  1. 开启了对隐藏窗口的检测
  2. 使用 AutoHotkey 类名获取窗口

每个 AutoHotkey 运行时都有类名为 AutoHotkey 的主窗口(这个窗口为什么称为主窗口?请参阅 A_ScriptHwnd),与是否创建自定义 GUI 窗口(自定义窗口的类名为 AutoHotkeyGUI)、是否隐藏托盘图标、是否打开调试窗口(这里的调试窗口即是主窗口,未打开时为隐藏状态)等无关。

说到这里,我想起了一个有趣的事情:为什么 AutoHotkey 被称为模拟多线程呢?从这里可以判断出,每个脚本运行时至少有两个线程:

  • 主线程,运行主窗口,负责接受消息、缓冲热键及伪线程的中断和切换等
    这里的描述可能不太准确和全面,不过大体上可以这么理解,其中的伪线程是指帮助中所说的线程概念(例如 Thread 中所描述的线程,注意帮助中除了 A_ScriptHwnd 外从未涉及到主线程)。
  • 脚本线程,实际执行脚本的线程,这不用多说了,它执行的就是我们写的脚本。

从 Microsoft Spy++ 中可以看到,实际上每个脚本也只有两个线程(你多开几个热键,多用几个计时器并不会出现更多线程)。

小结

尽管未谈到游戏,不过主要内容前面都说完了。因此,要检测 AutoHotkey 脚本的外挂只需在脚本启动及运行时定期执行:

DetectHiddenWindows, on
While WinExist("ahk_class AutoHotkey")
    WinKill

游戏不大可能用 AutoHotkey 写,这里的演示大家能看懂它的用途吧?不过这种检测方法只是我猜测的,对于如 AutoIt、按键精灵这样的脚本语言应该具有一定的可行性(如果是 C 语言这种估计没那么容易预防了)。正常的脚本如改键工具也无法例外了,有了解游戏开发的朋友能否能爆个真实情况。规避的方法也很简单,自己下载源码修改过类名编译喔。

本文与游戏关系不大,最开始的标题为脚本主窗口的妙用,不过这个标题是否更好呢?

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 160,881评论 4 368
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 68,052评论 1 301
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 110,598评论 0 250
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,407评论 0 217
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,823评论 3 294
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,872评论 1 224
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 32,037评论 2 317
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,778评论 0 204
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,505评论 1 247
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,745评论 2 253
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,233评论 1 264
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,568评论 3 260
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,231评论 3 241
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,141评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,939评论 0 201
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,954评论 2 283
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,784评论 2 275

推荐阅读更多精彩内容

  • 从三月份找实习到现在,面了一些公司,挂了不少,但最终还是拿到小米、百度、阿里、京东、新浪、CVTE、乐视家的研发岗...
    时芥蓝阅读 42,020评论 11 349
  • 注:中文应用部分仍需更新。转者按:本文属于零基础入门专题教程,原发表于 Download!网络密技王第三期,后转载...
    amnesiac阅读 3,284评论 0 6
  • Ubuntu的发音 Ubuntu,源于非洲祖鲁人和科萨人的语言,发作 oo-boon-too 的音。了解发音是有意...
    萤火虫de梦阅读 98,558评论 9 468
  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 170,589评论 25 707
  • 昨天最焦虑,尤其是中午做完磁共振后,听说周四还要再做一次的时候,感觉这手术遥遥无期了呢。 老爸平身第一次要上手术台...
    吴佟阅读 317评论 0 1