davestinhast/l4d2c-anticheat-re
GitHub: davestinhast/l4d2c-anticheat-re
对 L4D2Center 平台反作弊客户端的完整静态逆向工程分析,涵盖检测逻辑、HWID 采集、Protobuf 协议重建与绕过方法。
Stars: 1 | Forks: 0
## 目录
- [二进制标识](#identificación-del-binario)
- [AC 的功能](#lo-que-hace-el-ac--resumen-técnico)
- [方法论](#metodología)
- [仓库结构](#estructura-del-repositorio)
- [关键发现](#hallazgos-clave)
- [绕过向量图](#mapa-de-vectores-de-bypass)
## 二进制标识
```
Archivo: l4d2c_anticheat.exe
Tamaño: 44,877,952 bytes (42.80 MB)
Arquitectura: x86-64 (PE32+)
Lenguaje: Go (confirmado por múltiples indicadores del runtime)
Ofuscador: garble (obfuscación de nombres, tipos, strings y timestamp PE)
Framework UI: Wails v2 (Go + WebView2/Chromium embebido)
Servidor: https://l4d2center.com/0
Protocolo: HTTP/2 + TLS 1.2/1.3 + Protocol Buffers v3 (gRPC)
Firma digital: Authenticode -- "Editor verificado: L4D2Center" en UAC
Certificados: Auto-firmados (Root CA 10 años, hoja ~2.3 años)
Certificate Pinning: NO (usa el store de certificados de Windows)
```
## AC 的功能 -- 技术概述
### 启动时 (Startup -- 87 goroutines)
- 加载 WebView2 界面(内嵌 Chromium),带有深色控制台 UI
- 初始化窗口、进程和逆向工程 (RE) 工具的黑名单
- 加载 WMI 系统 (COM/DCOM) 以获取 HWID
- 配置指向 `l4d2center.com` 的 HTTP/2 客户端
- 配置身份验证 token 系统
- 向前端 JS 暴露三个方法:`StartL4D2` (ID=2), `ConnectL4D2Server` (ID=0), `FrontendReady` (ID=1)
### 连接到服务器时 (ConnectL4D2Server -- 4 goroutines)
**Goroutine 1 -- 身份验证**
- 从本地 Steam 客户端读取用户的 SteamID
- 执行 WMI 查询以收集完整的 HWID:
- `Win32_Processor.ProcessorId` -- CPU ID
- `Win32_DiskDrive.SerialNumber` / `Win32_DiskDrive.Model` -- 硬盘
- `Win32_BaseBoard.SerialNumber` / `Win32_BaseBoard.Model` -- 主板
- `Win32_VideoController.PNPDeviceID` / `.Name` -- GPU
- `Win32_OperatingSystem.BuildNumber` / `.Version` -- 操作系统
- 通过 `AAUUUh.InstallDate` 读取 Steam 安装日期(防小号)
- 向服务器 l4d2center.com 请求身份验证 token
- 检查账号是否为小号 (`GetSmurf`)
- 检查账号是否被封禁(通过 `Qi1Z8I.Banned` 调用 `GetBanned`)
**Goroutine 2 -- 检测配置**
- 从服务器下载 `CheatSigs` (W99qYP[]),即内存中的字节特征码
- 枚举游戏 addons 目录下的所有 `.vpk` 文件
- 初始化监控列表 (`_6di6zc0se2v`)
**Goroutine 3 -- 检测循环 (ticker 每 ~5-60秒)**
- 扫描窗口标题:调用 `EnumWindows` + `GetWindowTextW` 比对黑名单
- 扫描进程:调用 `CreateToolhelp32Snapshot` + `Process32First/Next` 比对黑名单
- 扫描游戏内存:调用 `ReadProcessMemory` 比对下载的 CheatSigs
- 监控 DLL 模块:调用 `Module32First/Next` 查找注入
- 每 ~30 秒向服务器发送一次心跳
- 每 ~120 秒使用 `BitBlt` 进行一次屏幕截图(PNG NRGBA 格式)
**Goroutine 4 -- 结果处理器**
- 检测到异常时:截取屏幕截图,向服务器报告,断开连接/封禁
- 控制台显示红色信息 (`#FF0000`) = 封禁/错误
### 主检测引擎 (dUgTofmw.ga4oovjHCfg -- 37 closures)
- 33 个检测 goroutines (func1-func33) + 4 个嵌套的子 goroutines
- 每个 goroutine 处理一个独立的检测向量
- 生产者-消费者模式:通过 `(*fcje4l4dl_uV).Feed` 在各个 goroutine 间传递数据
## 方法论
所有分析均以**静态**方式进行。该二进制文件从未被执行过。
使用的技术:
- **pclntab 提取**:Go 即使经过 garble 混淆也会保留一张函数表,借此可以恢复精确的 closure 计数和近似的调用树
- **类型反射元数据**:Go 在 `.rdata` 中嵌入了类型元数据。尽管 garble 混淆了名称,但其结构依然会暴露
- **Protobuf 注解**:`.rdata` 中的 `protobuf:"..."` 和 `json:"..."` 注解不会被 garble 混淆,这使得我们能够重建完整的 gRPC 消息 schema
- **字符串提取**:使用 Windows-1252 编码搜索字符串,以提取黑名单、endpoint 和 WMI 类名
- **Wails 绑定分析**:Wails 以明文形式向前端 JS 暴露方法,从而部分避开了 garble 的混淆
从二进制文件中估计约 190 个包里,成功识别出了 183 个 Go 包。
## 仓库结构
```
analysis/
binario.md Análisis PE: secciones, imports, metadatos
goroutines.md Arquitectura de goroutines y timing
protobuf_esquema.md Esquema protobuf completo reconstruido
hwid.md HWID: queries WMI, structs, bypass detallado
pipeline_hwid.md Pipeline HWID completo
listas_negras.md Blacklists completas de procesos y ventanas
logica_deteccion.md Lógica interna de detección (20 vectores)
protocolo_red.md Protocolo de red, autenticación, MITM
motor_deteccion.md Motor de detección principal
pdFrspK_G.md Motor hlavBkMcO: 644 verificaciones activas
paquetes_identificados.md Mapa completo de paquetes garble (183 paquetes)
frontend_ui.md Análisis de la UI: HTML, JavaScript, WebSocket IPC
bypass_guide.md Guía de bypass (20 vectores)
bypass/
bypass_firmas.md Bypass de firmas estáticas y CheatSigs
bypass_hwid.md Bypass del pipeline HWID con hook de vtable WMI
bypass_procesos.md Bypass de blacklist de procesos y ventanas
bypass_red.md MITM del protocolo gRPC sin certificate pinning
proto/
esquema.proto Definición protobuf reconstruida (16 mensajes)
```
## 关键发现
### 协议安全性
- **无证书绑定 (Certificate Pinning)** -- 使用 Burp/Fiddler 进行 MITM 无需任何修改即可生效
- TLS 协议栈内嵌于 Go 中,不使用 WinSSL/SChannel 或 OpenSSL
- 记录了三种 MITM 方法:Burp 代理、进程内 hook TLS、DNS 重定向
### HWID
- **5 个组件:** CPU、硬盘、GPU、主板、操作系统,通过 WMI COM 获取(`IWbemServices::ExecQuery` vtable 索引 20)
- 最终哈希:将 5 个组件串联后进行 xxHash64 哈希(通过 `BhCuafOD` 确认)
- 记录了通过 hook WMI vtable 实现的绕过方式
### 检测
- **动态 CheatSigs** -- 每次会话从服务器下载的字节特征码
- **778 个硬编码特征码** 分布在 5 个包中:`ra_94HIlnc6`(299) + `EyjsrRr`(162) + `WGfDxX0zz2M`(117) + `YCJ5PUz_M`(116) + `kNpc1A53`(84)
- **`hlavBkMcO`** 包含 **644 个子 closures** 并发在 `pdFrspK_G` 中执行
- **4 个列表中约有 62 条黑名单记录:** 窗口 (x32dbg, windbg, ghidra...)、进程 (aimware, fiddler, ollydbg...)、逆向工程 (RE) 工具 (dump, peek, kgdb)、.NET 工具 (dnspy, ilspy, ida -)
- **每 ~120 秒自动截图** 作为证据 (PNG NRGBA)
### 反分析
- **garble** -- 所有的包名、类型名和函数名均为随机字符串
- **PE 时间戳 = 0** -- 防止将其与构建日期进行关联
- **按序号调用的 API** -- ReadProcessMemory, OpenProcess 不会以字符串形式出现
### 先前分析的修正
- `reportZombies` = Go 的 runtime (GC),不是 AC 的函数
- `ReportZerolen`/`IsZerolen` = gopacket/802.11 库,不是 AC 的函数
- `mTkHARFkg8` = Go 的 `sync` 包 (WaitGroup, Mutex)
## 绕过向量图
| 向量 | 难度 | 方法 |
|--------|-----------|--------|
| 窗口黑名单 | 低 | 重命名调试器窗口 |
| 进程黑名单 | 低 | 重命名可执行文件 |
| HWID 流水线 | 中 | 使用 frida hook Z6ey1EJD.func1-11 |
| 内存 CheatSigs | 高 | 禁止注入进程 / hook VirtualQuery |
| 778 个静态特征码 | 高 | 多态 / 无已知特征码的代码 |
| `hlavBkMcO` 的 644 项检查 | 极高 | 完整的动态分析 + hook Feed() |
| DLL 模块 | 高 | 手动映射 (不使用 LoadLibrary) |
| os/exec 进程 | 中 | hook CreateProcess |
| SteamID | 中 | 需要合法账号 |
| InstallDate | 中 | hook 注册表读取 |
| Source Engine ConVars | 中 | hook ReadProcessMemory |
| 数据包捕获 (pcap) | 极高 | 使用虚拟 NIC 的虚拟机 |
| 网络协议 | 低 | Burp Suite (无证书绑定) |
标签:Go语言, gRPC, Python工具, 云资产清单, 协议分析, 反作弊绕过, 底层编程, 数据泄露, 日志审计, 权限提升, 游戏安全, 程序破解, 逆向工程