This is a project mainly for generating signatures/offsets for CS2, updating HL2SDK_CS2 cpp headers via Agent SKILLS & MCP Calls.
Our goal is to update signatures/offsets/cppheaders without human involved.
Currently, all signatures/offsets from CounterStrikeSharp and CS2Fixes can be updated automatically with this project.
- Feel free to contribute your SKILLS with PR! How to create SKILL? See here -
TODO: Add skill support for XXXXXXX
-
claude / codex
-
IDA Pro 9.0+
-
idalib (mandatory for
ida_analyze_bin.py) -
Clang-LLVM (mandatory for
run_cpp_tests.py)
uv syncDepotDownloader -app 730 -os all-platform [-dir "path/to/cs2_depot"]
uv run copy_depot_bin.py -gamever 14141 -platform all-platformuv run ida_analyze_bin.py -gamever 14141 [-oldgamever=14140] [-configyaml=path/to/config.yaml] [-modules=server] [-platform=windows] [-agent=claude/codex/"claude.cmd"/"codex.cmd"] [-maxretry=3] [-vcall_finder=g_pNetworkMessages|*] [-vcall_finder_model=gpt-4o] [-vcall_finder_apikey=your-key] [-vcall_finder_baseurl=https://api.example.com/v1] [-debug]-
Old signatures from
bin/{previous_gamever}/{module}/{symbol}.{platform}.yamlwill be used to find symbols in current version of game binaries directly through mcp call before actually running Agent SKILL(s). No token will be consumed in this case. -
-agent="claude.cmd"is for claude cli installed from Windows npm -
-vcall_finder=g_pNetworkMessagesfilters by an object declared in the module-levelvcall_finderconfig;-vcall_finder=*processes every declared object fromconfig.yaml. -
When
-vcall_finderis enabled, the script exports full disassembly and pseudocode for each referencing function intovcall_finder/{gamever}/{object_name}/{module}/{platform}/, then runs OpenAI SDK aggregation after all module/platform IDA work finishes; if a detail YAML already has a top-levelfound_vcall, that function skips the LLM call and reuses the cached result directly. -
After a successful LLM response, the script immediately writes back
found_vcall: [...]orfound_vcall: []to the corresponding detail YAML so reruns can skip that function's LLM call. -
vcall_finder/{gamever}/{object_name}.txtis now an appended YAML document stream; each record directly containsinsn_va,insn_disasm, andvfunc_offsetwithout a nestedfound_vcall:wrapper. -
Dedicated CLI parameters:
-vcall_finder_apikey: required whenvcall_finderaggregation is enabled-vcall_finder_baseurl: optional custom compatible base URL-vcall_finder_model: optional, defaults togpt-4ovcall_finderdoes not readOPENAI_API_KEY,OPENAI_API_BASE, orOPENAI_API_MODEL
uv run ida_analyze_bin.py -gamever=14141 -modules=networksystem -platform=windows -vcall_finder=g_pNetworkMessages -vcall_finder_model=gpt-4o -vcall_finder_apikey=your-key
uv run ida_analyze_bin.py -gamever=14141 -platform=windows,linux -vcall_finder=* -vcall_finder_model=gpt-4o -vcall_finder_apikey=your-key -vcall_finder_baseurl=https://api.example.com/v1Example outputs:
vcall_finder/14141/g_pNetworkMessages/networksystem/windows/sub_140123450.yamlvcall_finder/14141/g_pNetworkMessages.txt
uv run update_gamedata.py -gamever 14141 [-debug]uv run run_cpp_tests.py -gamever 14141 [-debug] [-fixheader] [-agent=claude/codex/"claude.cmd"/"codex.cmd"] - When with
-fixheader, an agent will be initiated to fix the mismatches in cpp headers.
dist/CounterStrikeSharp/config/addons/counterstrikesharp/gamedata/gamedata.json
-
2 skipped symbols.
-
GameEventManager: not used anymore by CSS. -
CEntityResourceManifest_AddResource: barely changes on game update.
dist/CS2Fixes/gamedata/cs2fixes.games.txt
-
1 skipped symbol.
-
CCSPlayerPawn_GetMaxSpeedbecause it is not a thing inserver.dll
dist/swiftlys2/plugin_files/gamedata/cs2/core/offsets.jsonc
dist/swiftlys2/plugin_files/gamedata/cs2/core/signatures.jsonc
- 44 skipped symbols.
dist/plugify-plugin-s2sdk/assets/gamedata.jsonc
- 14 skipped symbols.
dist/cs2kz-metamod/gamedata/cs2kz-core.games.txt
- 42 skipped symbols.
dist/modsharp-public/.asset/gamedata/core.games.jsonc
dist/modsharp-public/.asset/gamedata/engine.games.jsonc
dist/modsharp-public/.asset/gamedata/EntityEnhancement.games.jsonc
dist/modsharp-public/.asset/gamedata/log.games.jsonc
dist/modsharp-public/.asset/gamedata/server.games.jsonc
dist/modsharp-public/.asset/gamedata/tier0.games.jsonc
- 230 skipped symbols.
dist/cs2surf/gamedata/cs2surf-core.games.jsonc
- 26 skipped symbols.
CCSPlayerPawn for example.
-
Create
ida_preprocessor_scripts/find-CCSPlayerPawn_vtable.py -
ALWAYS check existing preprocessor scripts with
TARGET_CLASS_NAMESfor references. -
no LLM needed when finding vtable. everything done in the preprocessor script.
- with
expected_outputandexpected_input(optional) explicitly declared.
- name: find-CCSPlayerPawn_vtable
expected_output:
- CCSPlayerPawn_vtable.{platform}.yaml - name: CCSPlayerPawn_vtable
category: vtable-
Always make sure you have ida-pro-mcp server running.
-
For human contributor: You should write new initial prompts when looking for new symbols, DO NOT COPY-PASTE the initial prompts from README!!!
CBaseModelEntity_SetModel for example
- Search string "weapons/models/defuser/defuser.vmdl" in IDA, look for code snippet with following pattern in xrefs to the string:
v2 = a2;
v3 = (__int64)a1;
sub_180XXXXXX(a1, (__int64)"weapons/models/defuser/defuser.vmdl"); //This is CBaseModelEntity_SetModel, rename it to CBaseModelEntity_SetModel
sub_180YYYYYY(v3, v2);
v4 = (_DWORD *)sub_180ZZZZZZ(&unk_181AAAAAA, 0xFFFFFFFFi64);
if ( !v4 )
v4 = *(_DWORD **)(qword_181BBBBBB + 8);
if ( *v4 == 1 )
{
v5 = (__int64 *)(*(__int64 (__fastcall **)(__int64, const char *, _QWORD, _QWORD))(*(_QWORD *)qword_181CCCCCC + 48i64))(
qword_181CCCCCC,
"defuser_dropped",
0i64,
0i64);-
Create project-level skill
find-CBaseModelEntity_SetModelin ENGLISH according to what we did in IDA. -
The SKILL should generate
CBaseModelEntity_SetModel.{platform}.yaml, withfunc_sig. -
The SKILL should be working with both
server.dllandlibserver.so. -
DO NOT pack skill.
-
ALWAYS check existing SKILLs with
/write-func-as-yamlinvocation for references.
-
Create
ida_preprocessor_scripts/find-CBaseModelEntity_SetModel.py -
ALWAYS check existing preprocessor scripts with
TARGET_FUNCTION_NAMESfor references.
- with
expected_outputandexpected_input(optional) explicitly declared.
- name: find-CBaseModelEntity_SetModel
expected_output:
- CBaseModelEntity_SetModel.{platform}.yaml- Add the new symbol to
config.yaml, undersymbols.
- name: CBaseModelEntity_SetModel
catagoty: func
alias:
- CBaseModelEntity::SetModel-
Always make sure you have ida-pro-mcp server running.
-
For human contributor: You should write new initial prompts when looking for new symbols, DO NOT COPY-PASTE the initial prompts from README!!!
CBasePlayerController_Respawn for example
- Search string "GMR_BeginRound" in IDA and look for a function with reference to it, decompile the function who reference "GMR_BeginRound" and look for code pattern in the decompiled function:
do
{
//.......
if ( v31 )
{
if ( (*(unsigned __int8 (__fastcall **)(__int64))(*(_QWORD *)v31 + 3352LL))(v31) )
{
(*(void (__fastcall **)(__int64))(*(_QWORD *)v33 + 3368LL))(v33);
if ( v36 )
{
sub_1801C86D0(v36);
sub_18039EA00(v36, 32LL);
}
}
else if ( v36 && *(_BYTE *)(v30 + 836) == 3 || *(_BYTE *)(v30 + 836) == 2 )
{
sub_1809F9670(v36);
(*(void (__fastcall **)(__int64))(*(_QWORD *)v30 + 2176LL))(v30); // 2176LL is vfunc_offset for CBasePlayerController_Respawn
}
}
++v28;
}
while ( v28 != v29 );-
Create project-level skill
find-CBasePlayerController_Respawnin ENGLISH. -
The SKILL should generate
CBasePlayerController_Respawn.{platform}.yaml, withfunc_sig. (orvfunc_sigifCBasePlayerController_Respawnis too short or too generic). -
The SKILL should be working with both
server.dllandlibserver.so. -
DO NOT pack skill.
-
ALWAYS check existing SKILLs with
/write-vfunc-as-yamlinvocation for references.
-
Create
ida_preprocessor_scripts/find-CCSPlayerController_Respawn.py -
ALWAYS check existing preprocessor scripts with
TARGET_FUNCTION_NAMESfor references.
- with
expected_outputandexpected_input(optional) explicitly declared.
- name: find-CBasePlayerController_Respawn
expected_output:
- CBasePlayerController_Respawn.{platform}.yaml
expected_input:
- CBasePlayerController_vtable.{platform}.yaml - name: CBasePlayerController_Respawn
category: vfunc
alias:
- CBasePlayerController::Respawn-
Always make sure you have ida-pro-mcp server running.
-
For human contributor: You should write new initial prompts when looking for new symbols, DO NOT COPY-PASTE the initial prompts from README!!!
IGameSystem_InitAllSystems AND IGameSystem_InitAllSystems_pFirst for example
-
Search string "IGameSystem::InitAllSystems" in IDA, search xrefs for the string. the function with xref to the string is
IGameSystem_InitAllSystems. -
Rename it to
IGameSystem_InitAllSystemsif not renamed yet. -
Look for code pattern at very beginning of IGameSystem_InitAllSystems: "( i = qword_XXXXXX; i; i = *(_QWORD *)(i + 8) )"
-
Rename
qword_XXXXXXpreviously found toIGameSystem_InitAllSystems_pFirstif it was not renamed yet.
-
Create project-level skill
find-IGameSystem_InitAllSystems-AND-IGameSystem_InitAllSystems_pFirstin ENGLISH. -
The SKILL should generate
IGameSystem_InitAllSystems.{platform}.yaml, withfunc_sig. -
The SKILL should generate
IGameSystem_InitAllSystems_pFirst.{platform}.yaml, withgv_sig. -
DO NOT pack skill.
-
The SKILL should be working with both
server.dllandlibserver.so. -
ALWAYS check existing SKILLs with
/write-func-as-yamland/write-globalvar-as-yamlinvocation for references.
-
Create
ida_preprocessor_scripts/find-IGameSystem_InitAllSystems-AND-IGameSystem_InitAllSystems_pFirst.py -
ALWAYS check existing preprocessor scripts with
TARGET_FUNCTION_NAMESandTARGET_GLOBALVAR_NAMESfor references.
- with
expected_outputandexpected_input(optional) explicitly declared.
- name: find-IGameSystem_InitAllSystems-AND-IGameSystem_InitAllSystems_pFirst
expected_output:
- IGameSystem_InitAllSystems.{platform}.yaml
- IGameSystem_InitAllSystems_pFirst.{platform}.yaml - name: IGameSystem_InitAllSystems
category: func
alias:
- IGameSystem::InitAllSystems
- name: IGameSystem_InitAllSystems_pFirst
category: gv
alias:
- IGameSystem::InitAllSystems::pFirst-
Always make sure you have ida-pro-mcp server running.
-
For human contributor: You should write new initial prompts when looking for new symbols, DO NOT COPY-PASTE the initial prompts from README!!!
CGameResourceService_BuildResourceManifest AND CGameResourceService_m_pEntitySystem for example.
-
Search string "CGameResourceService::BuildResourceManifest(start)" in IDA, search xrefs for the string.
-
The xref should point to a function - this is
CGameResourceService_BuildResourceManifest. rename it toCGameResourceService_BuildResourceManifestif not renamed yet.
-
Create project-level skill
find-CGameResourceService_BuildResourceManifest-AND-CGameResourceService_m_pEntitySystemin ENGLISH. -
The SKILL should generate
CGameResourceService_BuildResourceManifest.{platform}.yaml, withfunc_sig. -
The SKILL should generate
CGameResourceService_m_pEntitySystem.{platform}.yaml, withoffsetandoffset_sig. -
DO NOT pack skill.
-
The SKILL should be working with both
server.dllandlibserver.so. -
ALWAYS check existing SKILLs with
/write-structoffset-as-yamlinvocation for references.
-
Create
ida_preprocessor_scripts/find-CGameResourceService_BuildResourceManifest-AND-CGameResourceService_m_pEntitySystem.py -
ALWAYS check existing preprocessor scripts with
TARGET_FUNCTION_NAMESandTARGET_STRUCT_MEMBER_NAMESfor references.
- with
expected_outputandexpected_input(optional) explicitly declared.
- name: find-CGameResourceService_BuildResourceManifest-AND-CGameResourceService_m_pEntitySystem
expected_output:
- CGameResourceService_BuildResourceManifest.{platform}.yaml
- CGameResourceService_m_pEntitySystem.{platform}.yaml - name: CGameResourceService_BuildResourceManifest
category: func
alias:
- CGameResourceService::BuildResourceManifest
- BuildResourceManifest
- name: CGameResourceService
category: struct
- name: CGameResourceService_m_pEntitySystem
category: structmember
struct: CGameResourceService
member: m_pEntitySystem
alias:
- GameEntitySystem
-
A patch SKILL locates a specific instruction inside a known function and generates replacement bytes to change its behavior at runtime (e.g., force/skip a branch, NOP a call). The target function should already have a corresponding find-SKILL output available (typically via
expected_input). -
Always make sure you have ida-pro-mcp server running.
-
For human contributor: You should write new initial prompts when looking for new symbols, DO NOT COPY-PASTE the initial prompts from README!!!
CCSPlayer_MovementServices_FullWalkMove_SpeedClamp for example — patching the velocity clamping jbe to an unconditional jmp inside CCSPlayer_MovementServices_FullWalkMove.
- Decompile CCSPlayer_MovementServices_FullWalkMove and look for code pattern - whatever a float > A square of whatever a float:
v20 = (float)((float)(v16 * v16) + (float)(v19 * v19)) + (float)(v17 * v17);
if ( v20 > (float)(v18 * v18) )
{
...velocity clamping logic...
}-
Disassemble around the comparison to find the exact conditional jump instruction.
-
Disassemble around the comparison address to find the comiss + jbe instruction pair.
Expected assembly pattern:
addss xmm2, xmm1 ; v20 = sum of squares
comiss xmm2, xmm0 ; compare v20 vs v18*v18
jbe loc_XXXXXXXX ; skip clamp block if v20 <= v18*v18
- Determine the patch bytes based on the instruction encoding.
* Near `jbe` (`0F 86 rel32` — 6 bytes) → `E9 <new_rel32> 90` (unconditional `jmp` + `nop`)
* Short `jbe` (`76 rel8` — 2 bytes) → `EB rel8` (unconditional `jmp short`)
-
Create project-level skill
find-CCSPlayer_MovementServices_FullWalkMove_SpeedClampin ENGLISH. -
The SKILL should generate
CCSPlayer_MovementServices_FullWalkMove.{platform}.yaml, withpatch_sigandpatch_bytes. -
DO NOT pack skill.
-
The SKILL should be working with both
server.dllandlibserver.so. -
ALWAYS check existing SKILL with
/write-patch-as-yamlinvocation for references.
-
Create
ida_preprocessor_scripts/find-CCSPlayer_MovementServices_FullWalkMove_SpeedClamp.py -
ALWAYS check existing preprocessor scripts with
TARGET_PATCH_NAMESfor references.
- with
expected_outputandexpected_input(optional) explicitly declared.
- name: find-CCSPlayer_MovementServices_FullWalkMove_SpeedClamp
expected_output:
- CCSPlayer_MovementServices_FullWalkMove_SpeedClamp.{platform}.yaml
expected_input:
- CCSPlayer_MovementServices_FullWalkMove.{platform}.yaml - name: CCSPlayer_MovementServices_FullWalkMove_SpeedClamp
category: patch
alias:
- ServerMovementUnlockThis is because the official idapro package is not compatible with IDA 9.0
Mitigation: Overwrite Python3**/Lib/site-packages/idapro/__init__.py with CS2_VibeSignatures/patched-py/Lib/site-packages/idapro/__init__.py.
Mitigation: You should run python py-activate-idalib.py under C:\Program Files\IDA Professional 9.0\idalib\python with administrator privilege.
Mitigation: Try set IDADIR=C:\Program Files\IDA Professional 9.0 or add IDADIR=C:\Program Files\IDA Professional 9.0 to your system environment.
@echo Download latest game binaries
uv run download_bin.py -gamever %CS2_GAMEVER%@echo Analyze game binaries
uv run ida_analyze_bin.py -gamever %CS2_GAMEVER% -agent="claude.cmd" -platform %CS2_PLATFORM% -debug@echo Update gamedata with generated yamls
uv run update_gamedata.py -gamever %CS2_GAMEVER% -debug@echo Find mismatches in CS2SDK headers and fix them
uv run run_cpp_tests.py -gamever %CS2_GAMEVER% -debug -fixheader -agent="claude.cmd"