项目通过 MinHook 挂载了 12 个关键函数:
这是项目最精巧的设计。Source 2 引擎提供了 schemasystem.dll,其中包含所有实体类的字段名→偏移映射。CSchemaOffset.cpp 在运行时遍历所有 TypeScope,动态读取 CSchemaClassBinding 结构的成员偏移,存入 unordered_map<string, unordered_map<string, uint32_t>>。
这意味着游戏更新导致实体字段偏移变化时,无需重新逆向,运行时自动解析。
对于非 Schema 暴露的函数(如 CalcWorldSpaceBones、ScreenTransform),项目通过 CBasePattern 在 DLL 加载时执行 AOB(Array of Bytes)扫描定位:
支持三种扫描类型:直接匹配、CALL指令追踪(SEARCH_TYPE_CALL)、LEA RIP相对寻址(SEARCH_TYPE_PTR2)。
拿到源码之后我想着能不能自己扫描进行适配,发现还真可以,使用AI进行批量文件扫描进行版本适配几乎可以无脑适配,但是适配之后骨骼和aimbot失效后续我也解决了!嘿嘿
编写了 Python 脚本 pattern_scan.py,通过 Boyer-Moore 风格的通配符匹配算法,一次性扫描所有目标 DLL:
对 8 个 DLL 的 35 个模式进行批量扫描,输出命中/缺失/歧义三类结果。
针对新版 Deadlock(ClientVersion 6536),扫描结果 30/32 OK,0 MISS,仅 CameraManager 和 CreateMaterial 存在歧义(2 处命中指向同一地址),确认无需修改即可运行。
本人英文不好所以手动给他添加了所有的翻译工程,然后重新编译即可

新增 LangHelper.hpp 翻译宏:
遍历 17 个菜单文件的数百处 XorStr("English") 替换为 L("English", "中文")。
同时为 ImGui 字体系统添加 CJK Merge Font(msyh.ttc),解决中文字符显示为方框的问题。
添加 /utf-8 MSVC 编译标志,确保 UTF-8 字符串在 GBK 环境下正确编译。
原始代码通过 GetDllDir() 获取 DLL 所在目录作为配置路径。由于 DLL 被注入器提取到 %TEMP%\随机目录,注入完成后被全零覆盖删除,导致配置不保存。
修改 CSettingsJson.cpp,新增 GetConfigDir():
配置保存到 %APPDATA%\LiveLock\,永久保留。

原始项目依赖 HeroSkeletonPairs.hpp 中的预先提取的骨骼映射表。由于 BoneExtractor 源码缺失,初版使用空存根导致自瞄无法锁定目标。
CAimbot.hpp 中 bool Active = false; 改为 true;,避免用户找不到开关。
从 UC 获取 Deadlock-BoneExtractor 源码,其对游戏 VPK 文件(Valve Pak)执行解析:
Andromeda 的自瞄和骨骼 ESP 都依赖 HeroSkeletonPairs.hpp 中预先提取的骨骼数据:
VPK读取 → 遍历 4966 个 .vmdl_c 条目
→ 过滤英雄模型路径
→ 解析 ValveResourceFormat 提取骨骼名称/ID
→ 构建 slotBones 部位分类 (Head/Neck/Torso/Arms/Legs)
→ 生成 C++ 头文件
源码仓库中的 HeroSkeletonPairs.hpp 仅包含一个空存根 g_HeroModelData = {},因为完整的骨骼数据由 PreBuildEvent 调用 BoneExtractor 运行生成后填入。此步骤需要 .NET SDK 且 BoneExtractor 源码在主仓库中缺失的。直接编译后所有 GetHitboxBones() 调用返回 nullptr,导致自瞄无法锁定目标和骨骼 ESP 无法绘制。
最初尝试了三种途径:
Deadlock 的资源存储在 game\citadel\pak01_dir.vpk(索引文件,6.5MB)和 pak01_000.vpk ~ pak01_270.vpk(数据分片)中。VPK v2 的文件头结构:
依赖 .NET 10.0 + ValveResourceFormat NuGet 包。生成 63 个英雄模型、总计 235KB 的 HeroSkeletonPairs.hpp。
目录树定位:TreeOffset = FileSize - TreeSize
目录树中每个文件条目为 18 字节:
在等待 .NET 10 SDK 期间,手动解析了 VPK v2 二进制格式:
条目按 Extension → Path → Filename 的三层树结构组织。遍历时以空字符串标记层级结束。
手动编写 Python VPK 解析器成功定位到扩展名 vmdl_c 下的 152 个英雄模型路径,但 latin-1 编码的目录名在 UTF-8 转换时触发 UnicodeDecodeError。
工具的核心逻辑:
Header: Magic(4B) + Version(4B) + TreeSize(4B) + FileDataSize(4B) + ...
Tree offset = FileSize - TreeSize
Entry: CRC(4B) + Preload(2B) + ArchiveIdx(2B) + Offset(4B) + Length(4B) + Term(2B)
关键 NuGet 依赖:
从 .vmdl_c 中提取的骨骼名(如 neck_0, spine_1, arm_upper_l, leg_lower_r)通过启发式规则映射到五个部位槽位:
成功定位 4966 个 vmdl_c 条目,但字符编码问题导致解析中止。最终 BoneExtractor 工具完美解决。
骨骼父子连接 (BonePair) 通过 .vmdl_c 中的层级关系构建,用于骨架 ESP 绘制连线。
输出:
跳过 89 个文件的原因是:turret、projectile、LOD 模型、spectre_hand 等非玩家骨骼。63 个有效模型覆盖了游戏中全部可玩英雄及其变体形态。
替换前后 DLL 大小对比:
注入游戏后验证:
成功定位 4966 个 vmdl_c 条目,但字符编码问题导致解析中止。最终 BoneExtractor 工具完美解决。
编译命令:
16 字节 Payload → AES-256-CBC(随机 IV)→ Base32 → "VITT-XXXXX-...":
GUI 卡密生成器,通过 libmysql C API 直连 MySQL,每张卡密记录到 deadlock.cards 表,支持查询状态。
本次开发涉及以下技术栈:
完整源代码和工具已整理归档,可作为 Source 2 引擎游戏学习的参考框架。
| Hook 点 |
所在 DLL |
用途 |
| CreateMove |
client.dll |
自瞄角度写入 |
| FireEventClientSide |
client.dll |
游戏事件拦截 |
| OnAddEntity / OnRemoveEntity |
client.dll |
实体缓存更新 |
| ParseMessage |
engine2.dll |
网络消息解析(伤害事件) |
| OnClientOutput |
engine2.dll |
客户端渲染回调 |
| GetMatricesForView |
client.dll |
视图矩阵获取 |
| DrawModel |
scenesystem.dll |
Chams 模型上色 |
| Present / ResizeBuffers |
GameOverlayRenderer64.dll |
D3D11 渲染层注入 |
| 方案 |
方法 |
结果 |
| IDA 提取 VITTLOCK.dll |
从 .rdata 段解析 STL 容器结构 |
数据嵌入在 133KB 静态初始化函数 sub_180008530 中,手动提取不现实 |
| 手写 VPK Python 解析器 |
按 VPK v2 二进制格式逐字节读取 |
成功定位目录树,但模型路径字符编码异常中止 |
| BoneExtractor 原版工具 |
从 GitHub 获取源码,配置 .NET 环境运行 |
成功生成 63 个英雄的完整数据 |
| 版本 |
DLL 大小 |
HeroSkeletonPairs.hpp |
| 空存根 |
6,353,920 bytes |
0 字节 |
| BoneExtractor 生成 |
6,578,176 bytes (+224KB) |
235KB, 63 模型 |
| 组件 |
版本 |
作用 |
| VS2026 Community |
18.6.2 |
主编译器 (v143 toolset) |
| VS2019 Community |
16.11.53 |
Wrapper 编译器 |
| .NET 8.0 SDK |
8.0.421 |
基础运行时 |
| .NET 10.0 SDK |
10.0.300 |
BoneExtractor |
| MySQL 9.3 |
- |
KeyGen 数据库 |
Andromeda-DeadLock-Base/ (VS DLL项目)
├── DllMain.cpp
├── DeadLock/
│ ├── Hook/
│ ├── SDK/
│ │ ├── CFunctionList.hpp
│ │ ├── CSchemaOffset.cpp
│ │ └── Interface/
│ └── Protobuf/
├── AndromedaClient/
│ ├── Features/
│ │ ├── CAimbot/
│ │ ├── CVisual/
│ │ ├── CMisc/
│ │ └── CHeroes/
│ └── GUI/
└── GameClient/
CBasePattern ScreenTransform = {
"ScreenTransform",
"33 C0 48 39 05 ? ? ? ? 0F 84",
CLIENT_DLL,
0,
SEARCH_TYPE_NONE
};
def scan(data, pat_bytes, mask):
n = len(pat_bytes)
first_byte = pat_bytes[first_lit]
pos = data.find(first_byte)
...
[内核课程]《Windows内核攻防实战》!从零到实战,融合AI与Windows内核攻防全技术栈,打造具备自动化能力的内核开发高手。
最后于 2026-6-7 09:37
被刘宝编辑
,原因: