Imported from mrc4tt/CS2_VibeSignatures (
.claude/skills/find-CNetworkMessages_dtor/SKILL.md). Install upstream withnpx skills add mrc4tt/CS2_VibeSignatures --skill find-CNetworkMessages_dtor. Copyright stays with the author.
Find CNetworkMessages_dtor
Locate CNetworkMessages_dtor vfunc in CS2 networksystem.dll or libnetworksystem.so using IDA Pro MCP tools.
Deterministic Preprocessor
Normal analyzer runs use ida_preprocessor_scripts/find-CNetworkMessages_dtor.py. It selects the ABI-defined
destructor slot from CNetworkMessages_vtable.{platform}.yaml and regenerates func_sig with the shared
deterministic signature generator. This Agent skill is only the fallback when that preprocessor fails; the trusted
finalizer replaces any Agent-provided func_sig from func_va before accepting the output.
Method
1. Load CNetworkMessages VTable from YAML
ALWAYS Use SKILL /get-vtable-from-yaml with class_name=CNetworkMessages.
If the skill returns an error, STOP and report to user.
Otherwise, extract:
vtable_numvfuncvtable_entries
2. Identify Destructor Candidates
The destructor is located in the last three vtable entries. Check the entries at indices:
vtable_numvfunc - 3vtable_numvfunc - 2vtable_numvfunc - 1
Read the function addresses from the vtable entries for these three slots.
3. Decompile and Identify the Destructor
Decompile all three candidate functions:
mcp__ida-pro-mcp__decompile addr="<candidate_1_addr>"
mcp__ida-pro-mcp__decompile addr="<candidate_2_addr>"
mcp__ida-pro-mcp__decompile addr="<candidate_3_addr>"
Windows (networksystem.dll)
The destructor has this characteristic two-argument pattern:
__int64 __fastcall CNetworkMessages_dtor(__int64 a1, char a2)
{
CNetworkMessages_dtor2(a1);
if ( (a2 & 1) != 0 )
(*(void (__fastcall **)(_QWORD, __int64))(*g_pMemAlloc + 24LL))(g_pMemAlloc, a1);
return a1;
}
Key identification rules for Windows:
- Takes two parameters:
(__int64 a1, char a2)(this + flags) - Calls another large destructor function (
CNetworkMessages_dtor2) with justa1 - Conditionally frees memory via
g_pMemAllocif(a2 & 1) != 0 - Returns
a1
The inner CNetworkMessages_dtor2 function is a large function that:
- Writes
CNetworkMessages::vftableback to*thisas the first operation:*(_QWORD *)a1 = &CNetworkMessages::vftable; - Contains a loop iterating 64 times destroying network message entries
- Calls multiple
CUtlSymbolTable::~CUtlSymbolTabledestructors - Ends by setting
CConCommandMemberAccessor<CNetworkMessages>::vftableon multiple member offsets
Linux (libnetworksystem.so)
The destructor has this characteristic single-argument pattern:
__int64 __fastcall CNetworkMessages_dtor(__int64 a1)
{
...
*(_QWORD *)a1 = CNetworkMessages_vtable;
...
}
Key identification rules for Linux:
- Takes one parameter:
(__int64 a1)(this only) - Writes
CNetworkMessages_vtable(orCNetworkMessages::vftable) to*(_QWORD *)a1as the first substantive operation - Is a very large function (hundreds of lines) that performs extensive cleanup
- Contains a loop destroying network message entries with
g_pMemAllocfree calls - Ends by writing
CConCommandMemberAccessorvtable pointers and conditionally calling unregister functions
4. Confirm the Destructor
The correct function among the three candidates is the one that matches the patterns above. Specifically:
- Windows: Look for the small wrapper that calls a large inner destructor and conditionally frees
this - Linux: Look for the very large function that starts by writing the vtable pointer to
*this
If none of the three candidates match, STOP and report to user.
5. Generate Function Signature
ALWAYS Use SKILL /generate-signature-for-function with addr=<dtor_func_addr> to generate a robust and unique func_sig for CNetworkMessages_dtor.
Use the returned validated func_sig in the next step.
6. Write IDA Analysis Output as YAML
ALWAYS Use SKILL /write-vfunc-as-yaml to write the analysis results.
Required parameters:
func_name:CNetworkMessages_dtorfunc_addr:<dtor_func_addr>func_sig: The validated signature from step 5vfunc_sig:None
VTable parameters:
vtable_name:CNetworkMessagesvfunc_offset:<target_vfunc_offset>in hex (computed asvfunc_index * 8)vfunc_index:<target_vfunc_index>
Function Characteristics
- Purpose: Destructor for the
CNetworkMessagessingleton; tears down all registered network messages, symbol tables, and member structures - Binary:
networksystem.dll/libnetworksystem.so - Parameters (Windows):
(this, char flags)whereflags & 1controls whether to free the object's memory - Parameters (Linux):
(this)only - Return value:
thispointer (Windows) / varies (Linux)
Discovery Strategy
- Load the existing
CNetworkMessages_vtableYAML to get the full vtable - Scan the last three vtable entries (
numvfunc - 3throughnumvfunc - 1) as destructor candidates - Decompile each candidate and match against the destructor patterns:
- Windows: small wrapper calling inner dtor + conditional
g_pMemAllocfree - Linux: large function starting with vtable pointer write-back
- Windows: small wrapper calling inner dtor + conditional
- Generate a stable
func_sigfrom the resolved destructor body
This is robust because:
- C++ destructors are always placed near the end of the vtable
- The destructor pattern (vtable write-back, extensive member cleanup) is highly distinctive
- Checking three candidates provides tolerance for vtable layout variations
Output YAML Format
The output YAML filename depends on the platform:
networksystem.dll->CNetworkMessages_dtor.windows.yamllibnetworksystem.so->CNetworkMessages_dtor.linux.yaml