写在前面
逆向方面我是自娱自乐的半吊子水平,文章中如果有一些理解上的错误,希望各位大佬不吝赐教~
目标
破解扫雷小游戏,一键通关
思路
1. 算法识别雷区
文字/图像识别扫雷界面,根据扫雷玩法自动计算雷区分布。如云顶之弈自动下棋外挂
优点
- 不用注入内存,不容易被反外挂检测到
- 不受游戏数据结构变动影响
缺点
- 考验开发+算法能力,需要反复调试才能实现完美的扫雷效果
- 过度依赖识别效果,并且有的时候一些雷没法通过推理判断出位置,因此准确率上可能存在一定偏差
2. 读内存识别雷区
通过分析内存数据,直接将雷区信息对应的数组信息读取出来。如LOL透视外挂
优点
- 准确率高
- 只需要简单分析内存数据即可,难度相对较低
缺点
- 需要注入进程读内存,可能会被反外挂程序检测
- 需要基于内存数据实现自动点击
- 游戏数据结构变动会导致数据读取异常
- 有时候需要计算指针找出基地址
3. 改游戏数据
绕过游戏本身的限制,直接修改雷区内存或外部数据文件,将雷的数量改为1,从而降低游戏难度。如吃鸡爆头挂、除草挂
优点
- 过程简单粗暴,可以使用CE傻瓜式修改
缺点
- 只能基于数据做修改,自由度较低
- 需要注入进程写内存,容易被反外挂+反作弊软件检测
- 数据修改不当可能会引起冲突,导致游戏崩溃
4. 调用关键API
省略中间过程,直接调用关键API。如原神瞬移挂,DNF全屏秒杀挂、人偶挂
优点
- 自由度高,可以任意组合游戏API实现各种效果
- 分析的过程中可以更透彻的了解游戏底层逻辑
缺点
- 需要注入进程远程调用函数,容易被反外挂软件检测
- 需要掌握逆向分析能力
- 调用不当可能会引起冲突,导致游戏崩溃
实战
找雷区
基于第一个方块的值,使用模糊查找雷区
小技巧:根据临近变量的内存地址找到雷区内存地址
解析数据
自动点击
使用spy++记录消息事件
代码实现
'''
Author : LzSkyline
Date : 2021-02-23
Description : 读内存自动扫雷
'''
from ctypes import *
import win32process
import win32api
import win32gui
import win32con
# 访问权限,权限越高越容易被检测
PROCESS_ALL_ACCESS = 0X1F0FFF # 最高权限
kernel32 = windll.LoadLibrary("kernel32.dll")
def wg():
# 根据标题获取窗口句柄
window_handle = win32gui.FindWindow(None, "扫雷")
if not window_handle:
return
# 根据窗口获取进程信息
_, pid = win32process.GetWindowThreadProcessId(window_handle)
if not pid:
return
# 获取进程操作权限
phand = win32api.OpenProcess(PROCESS_ALL_ACCESS, False, pid)
if not phand:
print("进程打开失败!")
return
mem_width = 32
# 创建一个有符号int类型
game_width = c_int(0)
# 读进程内存,将值写入指定地址
kernel32.ReadProcessMemory(int(phand), 0x01005334, byref(game_width), 2, None)
game_height = c_int(0)
kernel32.ReadProcessMemory(int(phand), 0x01005338, byref(game_height), 2, None)
# 创建一个指定大小的字节数组
addr = create_string_buffer(mem_width * game_height.value)
kernel32.ReadProcessMemory(int(phand), 0x01005361, byref(addr), mem_width * game_height.value, None)
for i in range(game_height.value):
for j in range(game_width.value):
current = hex(addr.value[i * mem_width + j])
print(current, end=" ")
if current == "0xf":
# 发送Windows消息,模拟点击事件
win32api.PostMessage(window_handle, win32con.WM_LBUTTONDOWN, win32con.MK_LBUTTON, win32api.MAKELONG(19 + j * 16, 63 + i * 16))
win32api.PostMessage(window_handle, win32con.WM_LBUTTONUP, 0, 0)
print()
# while True:
# kernel32.WriteProcessMemory(int(phand), 0x03128064, byref(c_int(sun)), 4, bytes(c_int(0)))
wg()
扩展1:修改手机单机游戏
1. Root后直接改内存
- Game Guardian
- Xposed框架 + 插件注入
2. 在虚拟空间中Root后直接改内存
- VirtualExposed:轻量(启动快占用低)、无广告、不稳定(闪退)
- 平行空间:稳定、有广告
- 虚拟大师(VMOS):手机上的VMware、重量级(启动慢占用高)、稳定、扩展性强
3. 逆向分析APP,修改关键代码
- smali文件(大多数APP应用)
- so文件(cocos2dx引擎开发的游戏)
- Assembly-CSharp.dll文件(Unity3D引擎开发的游戏)
- config json文件(大多数单机游戏)
扩展2:网络游戏破解思路
1. request请求并发
涉及到数据库操作可尝试
优点
- 因为并未修改数据所以不会被签名校验拦截,不需要考虑加密算法
- 可用来刷物品、刷点券
缺点
- 现在游戏关键操作加锁已经是基本功了,很少会有并发漏洞
- 行为非常明显,容易被风控系统拦截
2. request请求修改
当request请求未做签名校验时可尝试(还可以试一下SQL注入,可能有惊喜)
优点
- response数据被加密管我什么事
- 修改成功后数据会存储到服务器上,删除本地客户端也不会丢失
- 可以用来改物品使用数量、改充值金额
缺点
- 特征非常明显
- 如果request请求有签名校验,需要逆向分析加密算法
3. response数据修改
当response请求没有被加密时可尝试
优点
- request签名校验失败关我什么事
- 不用分析&修改客户端代码就可以解锁更多功能(本地VIP,回合制战斗加速、免广告特权)
- 可以用来刷物品数量、刷点券余额
- 与网络不好时的特征很相似,不容易被发现
缺点
- 每次客户端重新访问服务端接口更新数据时都需要修改,否则数据会还原
- 如果response数据被加密,需要逆向分析加密算法
2 条评论
大佬666
哈哈