--- name: re-anti-cheat description: > 反作弊对抗分析:EAC/BattlEye 驱动、内存校验、检测机制还原。 触发词:反作弊、EAC、BattlEye、内存校验、anti-cheat capabilities: [kernel-analysis] --- # 反作弊对抗分析(EAC / BattlEye / 内存校验) ## 何时使用 / 何时不用 - 用:分析反作弊组件(EAC / BattlEye / Vanguard 等)的驱动与服务、检测机制如何工作 - 用:游戏进程被反作弊拒绝/踢出后,理解"检测到了什么"(防御与研读视角) - 用:反作弊驱动的静态逆向(DriverEntry、IRP、内存校验逻辑)与内核调试观察 - 不用:制作或分发作弊程序 / 在真实游戏环境实施绕过(**明确禁止,见授权边界**) - 不用:只是游戏自身逻辑(内存修改、CE)→ [[re-game]] - 不用:普通驱动分析([[re-kernel]]);用户态反调试([[re-evasion]]) - **授权边界(必读)**:本技能仅限授权研究——自有设备、自有游戏账号、实验室环境、已获书面许可的安全研究。禁止:制作/分发作弊软件、在在线游戏中使用绕过手段获取不当优势、将检测机制分析用于破坏。所有动态实验在隔离沙箱([[re-analyze/platform-tips]] 最高原则)内进行;分析结论以防御与研究视角产出(理解检测面 → 改进检测),不产出可操作的绕过工具。 ## 工具准备 反作弊分析=驱动逆向 + 内核调试,全程隔离沙箱([[re-analyze/platform-tips]] 最高原则)。所有工具先验证再使用。 ### 驱动分析底座([[re-kernel]]) - 驱动静态:DriverEntry / IRP 分派 / 回调还原方法见 [[re-kernel]]「操作步骤」 - 反编译:[[re-ghidra]](默认,导入 .sys 后 Data Type Manager 载入内核类型) - 验证: 导入 EAC/BE 驱动 .sys 后 DriverEntry 能反编译 ### 内核调试([[re-windbg]]) - 双机/VM 串口(COM Named Pipe)或 KDNET 配置见 [[re-windbg]]「工具准备」 - **内核调试是观察反作弊驱动内核侧执行路径的主要手段**——不是整个反作弊系统唯一的动态手段(用户态组件另有观测面,见坑 1) - 验证: 内核会话 `lm` 能看到目标反作弊驱动模块,`.reload /f <驱动名>` 加载符号 ### 用户态快速定位([[re-x64dbg]] / [[re-windbg]]) - [[re-x64dbg]]:受保护进程之外的辅助组件(加载器、服务端)快速查看 - 目标可能带 PPL 保护但**非必然**——先查真实 protection level 再判定(`GetProcessInformation(..., ProcessProtectionLevelInfo, ...)` / Process Explorer / WinDbg),只有非 `PROTECTION_LEVEL_NONE` 才是 PPL(见坑 1) - 验证: `x64dbg` 能打开普通目标 exe ### 系统工具(服务/驱动枚举) - Windows 内置:`sc query` / `driverquery` / `fltmc`(文件系统过滤驱动列表) - Sysinternals(微软官网): Process Explorer(`process explorer` 查看受保护进程标记)、Sysmon - 验证: `driverquery` 输出驱动列表;`sc query EasyAntiCheat`(EAC 服务名按版本变化) ## 操作步骤 按顺序执行,每步产物(组件清单、IRP 表、校验逻辑笔记)记录证据路径 + sha256(见 [[re-triage]]),供报告引用。**所有步骤在授权范围与沙箱内进行**(授权边界见「何时使用」)。 1. **反作弊组件识别(驱动 / 服务)**: ```sh driverquery /v | findstr /i "anti cheat easy battle" # 驱动层组件 sc query | findstr /i "anti cheat easy battle vanguard" # 服务层组件 fltmc # 文件系统过滤驱动(完整性校验常在此) ``` - 典型组件:EAC(EasyAntiCheat.sys + 用户态加载器)、BE(BEDaisy.sys + 用户态服务)、Vanguard(vgk.sys 驱动 + 常驻服务);各厂商还有更新服务/反篡改守护 - 记录:组件清单(驱动名/服务名/安装路径)+ 驱动文件 sha256(版本锚点,见坑 3)+ 自保护状态(**查实际 protection level**,不要默认 PPL) 2. **驱动校验分析(内存扫描 / 完整性)**: - 静态还原([[re-kernel]] 方法):DriverEntry → IRP 分发表(`IRP_MJ_DEVICE_CONTROL` 等)→ 用户态 IOCTL 交互界面;重点找: - 完整性校验:定时/触发式校验游戏进程代码段与数据段哈希(`MmCopyVirtualMemory`/`KeStackAttachProcess` 类读取目标进程内存后计算) - 内存扫描:按特征扫描游戏进程内存(寻找修改后的代码/注入模块) - 回调注册:`PsSetCreateProcessNotifyRoutine`(监控进程创建)、`PsSetLoadImageNotifyRoutine`(监控模块加载)——校验逻辑的触发入口 - 用户态组件:加载器与服务([[re-binary-core]] 反编译)——心跳、报告通道、更新检查 - 产物:检测机制清单(触发点 → 校验内容 → 处置动作) 3. **检测规避思路(授权范围内研究)**: - 研究"检测机制如何工作"(防御视角),组织方式:检测面清单(完整性校验 / 内存特征 / 行为时序 / 驱动层监控) - 每个检测面的分析产出:检测条件、触发频率、报告通道(谁收到告警、什么格式) - **不实施**:在真实游戏环境中的规避、绕过工具开发、外挂分发——超出授权边界(坑 2) - 分析用途建议:检测改进(给厂商/防御侧)、规则编写([[re-ioc]] 思路:驱动特征、行为模式) 4. **内核对抗([[re-kernel]] 联动)**: - 内核调试会话([[re-windbg]]):断点打在回调函数 / 校验函数上观察触发时机与参数 - 反作弊驱动对调试器的反制:检测调试端口 / 清调试寄存器(`!dr`)/ 蓝屏诱饵——分析时记录反制手段(防御视角的"检测面"组成部分),应对一律在沙箱 + 快照([[re-analyze/platform-tips]] 最高原则) - 蓝屏风险:所有断点/触发实验在调试 VM 内做,操作前打快照([[re-kernel]] 坑 4) - 产物:调试会话记录 + 反制手段清单 5. **分析报告(合规边界)**: - 报告结构:授权范围声明 → 组件清单(版本/哈希)→ 检测机制(触发点/内容/动作)→ 反制手段 → 防御建议 - 合规要点:报告标注授权环境与用途;不包含可操作的绕过步骤;不发布驱动密钥/签名材料;敏感结论走负责任披露(厂商安全团队/漏洞奖励) - 产物:报告存档(sha256) ## 跨域联合 - [[re-kernel]]:驱动逆向方法论底座(DriverEntry / IRP / 回调)+ 内核调试配合——本技能固定依赖 - [[re-windbg]]:内核调试会话、`!analyze -v`、断点与现场恢复(观察内核驱动执行路径的主要手段) - [[re-x64dbg]]:用户态辅助组件(加载器/服务)快速定位 - [[re-game]]:游戏侧内存修改 / CE 思路——检测机制的"被检测对象",对照理解 - [[re-evasion]]:用户态反调试 / 反分析对抗框架(与驱动层反制对照) - [[re-ioc]]:检测特征 → YARA 规则 / 行为模式产出(防御视角) - [[re-sandbox]] / [[re-analyze/platform-tips]]:隔离沙箱 + 快照最高原则(蓝屏与样本风险) ## 常见坑与陷阱 - **把 attach 失败一律判成 PPL**:现象——x64dbg/WinDbg 用户态 attach 目标被拒绝("无法附加")或附加后进程立即退出/蓝屏,遂记为"目标是 PPL";原因——**PPL 是 Windows 自身的进程保护机制,有明确的 protection level 与签名者语义**(`PROCESS_PROTECTION_LEVEL_INFORMATION` 区分 `PROTECTION_LEVEL_NONE`=未受保护、`PROTECTION_LEVEL_PPL_APP`=第三方应用启用了进程保护等),**不存在"加载了反作弊驱动 ⇒ 游戏自动成为 PPL"这样的通用规则**——反作弊完全可以只在内核侧做访问过滤、对象回调、完整性校验和反调试,而目标进程仍是普通进程;**attach 被拒只是现象,不能据此反推 PPL**;对策——先查**真实** protection level(`GetProcessInformation(..., ProcessProtectionLevelInfo, ...)`、Process Explorer 的 Protection 列、WinDbg 读 `EPROCESS.Protection`),只有非 `PROTECTION_LEVEL_NONE` 才叫 PPL;普通进程 attach 失败时分别排查:反作弊的句柄访问过滤 / 对象回调(`ObRegisterCallbacks` 剥调试权限)、用户态反调试、自终止策略、调试器检测(调试端口、调试寄存器、`NtQueryInformationProcess` 调试状态) - **"内核调试是唯一动态手段"**:现象——因用户态 attach 不通,就把整个分析限制在内核调试一条路上,跳过其他可观测面;原因——把"驱动内核侧"等同于"整个反作弊系统";对策——**分析内核驱动内部执行路径时以隔离环境下的内核调试为主**(双机/VM,[[re-windbg]],目标在 VM 内、调试器在宿主,断点下在内核回调/校验函数而非游戏进程内,一切在沙箱 + 快照内,蓝屏即回滚);但用户态 service/launcher、IPC、文件与注册表活动、ETW/系统事件、网络交互、进程与模块生命周期**各有对应的动态观测方法**,不因 attach 不通而失效 - **法律边界(仅研究授权环境)**:现象——分析被用于制作外挂 / 在线作弊 / 出售绕过工具,触发法律与游戏厂商反制(封禁、诉讼);原因——反作弊分析天然接近作弊技术,绕过手段在真实游戏环境使用即侵权/违约;对策——严格限定授权范围(自有设备、自有账号、书面许可的实验室);报告只做防御向(检测机制如何工作、如何改进检测);不发布可操作工具、不公开驱动敏感材料;以"理解检测面"为边界,不以"绕过成功"为产出 - **反作弊更新频繁(结论过期)**:现象——上周分析出的函数地址/偏移/检测点全部失效,报告结论"过时";原因——EAC/BE 数天一个版本,驱动加壳/混淆与结构变动频繁;对策——分析必须锚定版本:记录驱动 sha256、文件版本号、分析时间(步骤 1);报告注明版本与日期;分析方法(IRP 还原、回调枚举、IOCTL 解码)跨版本复用,具体地址/偏移不跨版本复用 - **绕过技术对抗升级(分析方向错位)**:现象——分析出的"弱点"很快被修复或触发新检测,陷入逐点对抗;原因——反作弊是持续对抗工程,单点绕过必然升级;对策——把分析定位为"理解检测面"(系统视角)而非"制造漏洞"(单点视角);产出按检测面组织(完整性/内存/行为/驱动层)并给出防御建议;对抗升级的案例本身就是防御研究素材(记录新旧检测机制对比) - **CSAuth3 心跳协议自包含可脱机复现(GameGuard)**:现象——反作弊心跳包(头部 KDF + 载荷变换 + 双重 CRC)黑盒猜测易错,静态逆向无从下手;原因——CSAuth3 是 GameMon 客户端与对端的心跳问答循环(对端发挑战包、客户端回心跳包),**全部密码学材料是硬编码常量**(Blowfish K=0x91284712、公开 π 表),仅 counter 与 prev_size 随会话变化——首包 seed=0(counter=0、K=0x91284712、载荷 8 字节全 0 且空载荷不 scramble);对策——按"头部 KDF 解密 → CRC1 → Blowfish 逆变换 → CRC2"逐层还原;**scramble/descramble 是同一函数**(Blowfish 加解密对称性:发送方明文 TLV 跑一遍 `bf_dec` 成线上密文,接收方再跑 `bf_dec` 还原);构造包时必须**先 scramble 再算 CRC2**(CRC2 校验的是 descramble 之后的载荷);密钥编排离线确定 → 纯脱机心跳可行 - **错误码表是心跳重放的黑盒加速器**:现象——构造的心跳包被对端拒绝,不知道卡在哪层校验;原因——CSAuth3 对每类校验失败返回不同错误码(0xBAE 首包标志正常、0xCE9 CRC1 不匹配、0xCE8 CRC2 严格不匹配、0xBB8 CRC2 映射模式基值、0xCE5 seq>5、0xCEA magic≠0x1E、0xCEF/0xCEC size 越界、0xD4A body 未 8 对齐、0xD52 消息数不符、0xD913 消息类型1 哈希失败等);对策——按错误码反推失败层(≥0xBB8 的错误置错误标志 → 后续 Check 假通过、Get 停发);hook 客户端处理挑战包的 callback handler 可直接获知该发什么,转发即可 - **CR3 加密(EAC 类内核反作弊)**:现象——读 `_KPROCESS.DirectoryTableBase` 拿到的是错误 CR3,遍历进程内存全乱/访问异常;原因——反作弊接管内核异常并把 DirectoryTableBase 写错值,附加/读进程等需访问该字段的操作触发异常时,在接管后的异常回调里才修复真值;对策——获取真实 CR3 的常用法:**页帧 ListEntry.Flink 指向加密后的进程 K/EPROCESS 结构指针**,遍历 `MmPfnDataBase` 逐页帧比对 Flink 解密值是否为目标进程结构,命中即得真实 CR3;注意版本差异:Win11 24H2 及部分高版本 Win10/11 的加密算法(`MiSetPageTablePfnBuddy` 可见)与其他版本不同,需按版本适配;分析前先确认目标系统版本(见 [[re-kernel]] 结构随版本变化坑)