2017-09
浅谈外挂常识和如何防御 - https://www.cnblogs.com/xingzheai/p/16076865.html
图色脚本
图色可以做到的
一,凡文字信息都可以用二值化来达到100%准确获取,比如金币,疲劳度,等级,地区,等等。
二,怪物定位:要么自动锁定怪物,要么有tab键选怪,要么小地图有怪物图标供识别,要么游戏有召唤师职业不需要定位怪也能让召唤物打怪。
三,人物定位:要么有自动寻路,要么小地图有坐标,要么有能力识别小地图来反推人物坐标。
四,拾物定位:能定位怪物坐标就能定位掉宝坐标,因为怪物死亡的坐标(也就是怪物最后一次出现的坐标)就是掉宝坐标,关掉环境音,拾取的时候不断检测声音,无入包的声音就捡取完毕。
五,寻路:要么有自动寻路,要么有能力绘制地图加a*寻路,要求寻路过程中能不断获取到两个值,人物坐标,人物朝向,然后不断调整人物朝向往目的地前进就行(只知道人物初始朝向,然后不断维护这个值也可以,这样可以不用检测人物朝向,只需要算)。
这里要注意的一点是任何东西都可以不稳定,寻路算法不能不稳定,而稳定的寻路算法依赖于精确的人物定位,所以有人物坐标显示的游戏是最好
https://zhuanlan.zhihu.com/p/94302055 https://www.zhihu.com/search?q=%E5%9B%BE%E8%89%B2%E8%87%AA%E5%8A%A8%E5%8C%96&utm_content=search_suggestion&type=content
上牛刀
OpenCV
OpenCV 模版匹配: 简单方便, 缺点: 不具有旋转不变性、不具有尺度不变性; 特征匹配: 缩放/遮挡/旋转/透视形变, 均可处理!!
OCR
嫌字库麻烦可以上一些开源的OCR库, 例如: Paddle OCR
Lobe
https://www.lobe.ai/examples https://github.com/lobe
Lobe 是微软在 2018年收购的一家公司的产品,当然现在已经我们可以当作完全是微软的产品了,这是一款让非专业人士也能通过机器学习的方法来构建 AI 模型的应用。 智障级别的难度
Halcon
Halcon 工业级图像处理神器, 跟AI识别有关
键鼠模拟
windows 消息机制
Windows发出的一个通知,告诉应用程序某个事件发生了。例如,单击鼠标、改变窗口尺寸、按下键盘上的一个键都会使Windows发送一个消息给应用程序。
Windows的消息系统是由3个部分组成的:
-
消息队列。Windows能够为所有的应用程序维护一个消息队列。应用程序必须从消息队列中获取 消息,然后分派给某个窗口。
-
消息循环。通过这个循环机制应用程序从消息队列中检索消息,再把它分派给适当的窗口,然 后继续从消息队列中检索下一条消息,再分派给适当的窗口,依次进行。
-
窗口过程。每个窗口都有一个窗口过程来接收传递给窗口的消息,它的任务就是获取消息然后 响应它。窗口过程是一个回调函数;处理了一个消息后,它通常要返回一个值给Windows。 注意: 回调函数是程序中的一种函数,它是由Windows或外部模块调用的。
Windows消息控制中心一般是三层结, 其顶Application对象。 第三级控制中心就是Windows窗体对象,每一个窗体都有一个端就是Windows内核。Windows内核维护着一个消息队列 第二级控制中心从这个消息队列中获取属于自己管辖的消息,后做出处理,有些消息直接处理掉,有些还要发送给下一级窗体(Window)或控件(Control)。第二级控制中心一般是各Windows应用程序的默认的窗体过程,这个过程负责处理各种接收到的消息。
一个消息从产生到被一个窗口响应,其中有5个步骤:
- 系统中发生了某个事件。
- Windows把这个事件翻译为消息,然后把它放到消息队列中。
- 应用程序从消息队列中接收到这个消息,把它存放在TMsg记录中。
- 应用程序把消息传递给一个适当的窗口的窗口过程。
- 窗口过程响应这个消息并进行处理。
步骤3和4构成了应用程序的消息循环。消息循环往往是Windows应用程序的核心,因为消息循环使一个应用程序能够响应外部的事件。消息循环的任务就是从消息队列中检索消息,然后把消息传递给适当的窗口。如果消息队列中没有消息,Windows就允许其他应用程序处理它们的消息。
[参考下: (windows 的各种钩子/消息钩子(Message Hook)) ]
OP 插件
https://github.com/WallBreaker2/op OP(operator & open)是一个开源插件(类似大漠插件).主要功能有:Windows消息模拟,后台截图,找图,字符识别(OCR)等。使用c++编写,源代码可编译为32/64位dll.op插件提供了两类接口:1)原生c++接口,可以让c/c++开发者方便调用;2)com接口,支持大多数编译型语言(c++,c#,vb,delphi等 以及脚本语言(python,lua等)的调用
源码编译
blackbone(静态编译,链接方式MT) 编译完成后,设置环境变量 BLACKBONE_ROOT 为源码根目录(例如D:\workspace\Blackbone) kiero(已在源码内,无需安装) minhook(已在源码内,无需安装) QT5.12(可选) 安装完成后设置环境变量QT_ROOT为Qt安装目录下的版本目录,例如D:\workspace\QT\5.12.12 Python32/64(可选) 安装完成后设置环境变量 PYTHON32_ROOT 为32位python安装目录,PYTHON64_ROOT 为64位python安装目录
-
op 项目 git clone https://github.com/WallBreaker2/op.git
-
编译 Blackbone
git clone https://github.com/DarthTon/Blackbone.git
cd E:\projects-cpp\Blackbone\src
cmake . // 生成 vs 项目
set BLACKBONE_ROOT=E:\projects-cpp\Blackbone
set PYTHON64_ROOT=C:\Users\yang\AppData\Local\Programs\Python\Python39
cmake .
不注入DLL 游戏窗口 后台键盘模拟?
键盘模拟无外乎keybd_event 和 SendInput 很多游戏都用 DirectX ,利用 DirectInput 绕过Windows的消息机制直接和硬件打交道来接收按键信息的。这时候要在模拟键鼠消息就 只有注入游戏进程拦截 DirectInput 过滤API。
驱动模拟
64位版本的 Windows只加载设备驱动程序,这些驱动程序由一个公共CA签发的代码签名证书签署,如Verisign、Thawte等。WinIo64 除非获得了代码签名证书,否则系统不能部署在生产机器上。 驱动模拟只能全局且前台模拟… 博客园 书侍 - 模拟键盘按键
WinIo
WinIO程序库允许在32位的Windows应用程序中直接对I/O端口和物理内存进行存取操作。通过使用一种内核模式的设备驱动器和其它几种底层编程技巧,它绕过了Windows系统的保护机制。
它这个驱动没有签名需要自己搞 利用winIO3.0进行windows10 64bit端口读取
Interception
它的驱动有数字签名, 甚至可以拦截 (CTRL+ALT+DELETE) Support is still Windows only (from Windows XP to Windows 10).嗯.. 支持到win10 但也是只能前台模拟..
按键模拟
void passKey(){
InterceptionContext context = interception_create_context();
InterceptionKeyStroke keyStroke[2];
keyStroke[0].code = MapVirtualKey('A', MAPVK_VK_TO_VSC);//a 键码; win32的 api
keyStroke[0].state = INTERCEPTION_KEY_DOWN;//按下
keyStroke[1].code = keyStroke[0].code;
keyStroke[1].state = INTERCEPTION_KEY_UP;//弹起
//发送
interception_send(context, INTERCEPTION_KEYBOARD(0), (InterceptionStroke*)keyStroke, _countof(keyStroke));
interception_destroy_context(context);
}鼠标模拟
//鼠标移动到屏幕中间 右键
void muni(){
//初始化上下文
InterceptionContext context = interception_create_context();
// 鼠标移动到屏幕中间
InterceptionMouseStroke mouseStroke[3];
mouseStroke[0].flags = INTERCEPTION_MOUSE_MOVE_ABSOLUTE;
mouseStroke[0].x = 65535 / 2; // 坐标取值范围是0-65535
mouseStroke[0].y = 65535 / 2;
// 点击鼠标右键
mouseStroke[1].state = INTERCEPTION_MOUSE_RIGHT_BUTTON_DOWN;
mouseStroke[2].state = INTERCEPTION_MOUSE_RIGHT_BUTTON_UP;
//发送
interception_send(context, INTERCEPTION_MOUSE(0), (InterceptionStroke*)mouseStroke, _countof(mouseStroke));
//销毁
interception_destroy_context(context);
}参考笔记 N_QT.md Interception N_QT
无解 必须DLL注入
xp下对dinput8.dll 游戏键盘输入的模拟 非函数hook
驱动级的模拟, 都是全局模拟, 不能指定句柄后台; 若想 hook DirectInput 输入, 必须DLL注入拦截dx接口函数;
其实原理很简单,拦截dx接口函数,就是让dx的函数在执行之前或之后,首先执行我们的代码, 比如你要读写屏,肯定要在其之前Hook 比如你要发送键盘鼠标消息,那就要在DInput的获取数据接口执行之后,替换其数据,让其传出我们的数据,就可以达到后台DX键盘或者鼠标了
对DInput的hook,鼠标和键盘以及手柄都是通过这个来获取数据的,hook目标:GetDeviceData,GetDeviceState,一个缓冲模式,一个立即模式,键盘,鼠标,手柄数值统统按照常量,定义在 DX SDK头文件中 参考: https://www.cnblogs.com/rogee/archive/2010/09/16/1828258.html
AutoHotkey
https://www.autohotkey.com/ https://wyagd001.github.io/v2/docs/index.htm
按键重映射
https://wyagd001.github.io/v2/docs/Hotkeys.htm#combo
短按3键 映射为 长按F键300毫秒
#Requires AutoHotkey v2.0
3::
{
; 阻止3键的默认功能
; 按下F键
Send "{f Down}"
; 保持300毫秒
Sleep 300
; 释放F键
Send "{f Up}"
}
如果3秒之前按过[CTRL键], 则将[空格键]输入 映射为 [CTRL键] + [空格键] 否则保持原来的[空格键]输入
#Requires AutoHotkey v2.0
turnJumpActiveTimestampe := 0
turnJumpActiveTimestampeTimeout := 3000
;(~)前缀用于表示:当热键触发时,不阻止该按键的原始功能
~Ctrl::
{
global turnJumpActiveTimestampe
turnJumpActiveTimestampe := A_TickCount
return
}
;重映射 Space 键
$Space::
{
global turnJumpActiveTimestampe,turnJumpActiveTimestampeTimeout
if A_TickCount - turnJumpActiveTimestampe < turnJumpActiveTimestampeTimeout
{
turnJumpActiveTimestampe := A_TickCount
Send "^{Space}"
}
else
{
Send "{Space}"
}
return
}
$脚本使用 Send 函数发送包含了热键自身的按键时才需要使用此符号, 此时可以避免触发它自己.
#HotIf WinActive("new 1 - Notepad++")
寻路算法
1. A*算法
A算法是一种启发式搜索算法,它利用启发函数(heuristic function)来评估节点的估价函数(estimated cost function),从而寻找最短路径。A算法综合考虑了节点的实际代价和到目标节点的预计代价,因此能够快速而准确地寻找最短路径; 不一定最短,A*算法并不一定能够找到最短路径,但它通常可以找到接近最短路径的解决方案
把一张地图分为一个二维数组,每一个格子代表一个路点;
A B C
D E F
G H I
假设最小方格的边长是 10;
10 10 10
10 10 10
10 10 10
从 E 格子出发,到达 A 格子的距离为 (10^2 + 10^2) 的开方, 这里可以简化为14 (忽略浮点数, 简化算法的计算难度)
评估值 F
每一个路点都有一个评估值F,其中 F = G + H
G 值是起点移动到指定方格(或者说是下一个点)的移动代价 H 是指定的方格移动到终点的估算成本 (注意该值, 不需要考虑障碍,只需考虑起始点和目标点即可)
H值计算方式
H值的计算方式有如下两种:
-
计算横向和纵向移动的距离,不能斜着走
-
比如该点和目标点 为对角顶点组成的矩行的边长是a 和 b,那么H值是
min(a,b) * 14 + abs(a - b) * 10
算法思路
这个算法需要两个数组,openList 和 closeList openList 里面存放的是当前状态可以到达的路点 closeList 存放不能到达的路点和已经经过判断的路点;具体步骤如下:
-
从当前选中路点a出发,总共有8个路点可能到达,假设可到达的节点为b 如果b是障碍点,则直接加入closeList; 如果b在openList中,当且仅当b的G值小于点a的G值(下一点的代价)时,更新a的G值,并且将路点b的父节点设置为当前a; 如果b在closeList中,则跳过该点的判断
-
如果目标点进入了 openList,则遍历停止,找到可到达路径; 由于每个节点都保存着到达自己的父节点,所以拿到目标点,一直拿到它的父节点就可以找到到达路径; 如果 openList 为空时还没找都目标路点,则不可到达,算法结束;否则进入下一个步骤;
-
遍历 openList 的路点,选出F值最小的那个点,如果有多个最小值,可以选择第一个最小值,也可以选择多个最小值中的最后一个,最后的表现就是到达目标点的最短路径可能有多条; 然后把这个点当做选中路点,进行步骤1;
2. Dijkstra算法
Dijkstra算法是一种贪心算法,它从起点开始,每次选择当前代价最小的节点作为下一个节点。通过不断更新节点的代价,最终可以找到起点到终点的最短路径。
3. Bellman-Ford算法
Bellman-Ford算法是一种动态规划算法,它通过不断更新节点的代价,直到收敛到最短路径。相比于Dijkstra算法,Bellman-Ford算法能够处理负权边的情况。
4. Floyd-Warshall算法
Floyd-Warshall算法是一种动态规划算法,它能够计算出图中任意两点之间的最短路径。Floyd-Warshall算法通过不断更新节点之间的代价,直到收敛到最短路径。
关于区域内的寻路
一般人会将区域网格化,这样会有至少几万个结点,然后在里面用a*来寻路,这个是很常见的做法。 较科学的做法是可视图寻路,
本来地图里面是只有障碍物和起终点的,现在将所有障碍物的顶点两两用直线连接起来,前提是它们之间没有障碍物阻挡,包括起点和终点也要参与连接,这个新图里面的顶点数是所有障碍物的顶点再加上2(起点和终点),然后在这个图里面寻路
一些零碎的经验之谈 - https://zhuanlan.zhihu.com/p/157927242