$npx -y skills add HLND2T/CS2_VibeSignatures --skill find-CNetworkMessages_vtable-decompilesFind and identify CNetworkMessages_AllowAdditionalMessageRegistration and CNetworkMessages_IsAdditionalMessageRegistrationAllowed virtual functions in CS2 binary using IDA Pro MCP. Use this skill when reverse engineering CS2 networksystem.dll or libnetworksystem.so to locate both
| 1 | # Find CNetworkMessages_AllowAdditionalMessageRegistration and CNetworkMessages_IsAdditionalMessageRegistrationAllowed |
| 2 | |
| 3 | Locate `CNetworkMessages_AllowAdditionalMessageRegistration` and `CNetworkMessages_IsAdditionalMessageRegistrationAllowed` vfuncs in CS2 `networksystem.dll` or `libnetworksystem.so` using IDA Pro MCP tools. |
| 4 | |
| 5 | ## Method |
| 6 | |
| 7 | ### 1. Load CNetworkMessages_RegisterNetworkFieldChangeCallbackInternal from YAML |
| 8 | |
| 9 | **ALWAYS** Use SKILL `/get-func-from-yaml` with `func_name=CNetworkMessages_RegisterNetworkFieldChangeCallbackInternal`. |
| 10 | |
| 11 | If the skill returns an error, **STOP** and report to user. |
| 12 | |
| 13 | Otherwise, extract: |
| 14 | - `vfunc_index` of `CNetworkMessages_RegisterNetworkFieldChangeCallbackInternal` |
| 15 | - `vfunc_offset` of `CNetworkMessages_RegisterNetworkFieldChangeCallbackInternal` |
| 16 | |
| 17 | ### 2. Load CNetworkMessages VTable from YAML |
| 18 | |
| 19 | **ALWAYS** Use SKILL `/get-vtable-from-yaml` with `class_name=CNetworkMessages`. |
| 20 | |
| 21 | If the skill returns an error, **STOP** and report to user. |
| 22 | |
| 23 | Otherwise, extract: |
| 24 | - `vtable_numvfunc` |
| 25 | - `vtable_entries` |
| 26 | |
| 27 | ### 3. Resolve the Two Adjacent Slots |
| 28 | |
| 29 | Compute the candidate slots: |
| 30 | |
| 31 | - `allow_vfunc_index = CNetworkMessages_RegisterNetworkFieldChangeCallbackInternal.vfunc_index + 1` |
| 32 | - `allow_vfunc_offset = CNetworkMessages_RegisterNetworkFieldChangeCallbackInternal.vfunc_offset + 8` |
| 33 | - `isallowed_vfunc_index = CNetworkMessages_RegisterNetworkFieldChangeCallbackInternal.vfunc_index + 2` |
| 34 | - `isallowed_vfunc_offset = CNetworkMessages_RegisterNetworkFieldChangeCallbackInternal.vfunc_offset + 16` |
| 35 | |
| 36 | Validate that `isallowed_vfunc_index < vtable_numvfunc`, then read: |
| 37 | |
| 38 | - `allow_func_addr = CNetworkMessages_vtable[allow_vfunc_index]` |
| 39 | - `isallowed_func_addr = CNetworkMessages_vtable[isallowed_vfunc_index]` |
| 40 | |
| 41 | This adjacent-slot rule is required because `AllowAdditionalMessageRegistration` and `IsAdditionalMessageRegistrationAllowed` immediately follow `RegisterNetworkFieldChangeCallbackInternal` in the `CNetworkMessages` vtable. |
| 42 | |
| 43 | ### 4. Decompile Both Candidate Functions |
| 44 | |
| 45 | Decompile both candidates: |
| 46 | |
| 47 | ```text |
| 48 | mcp__ida-pro-mcp__decompile addr="<allow_func_addr>" |
| 49 | mcp__ida-pro-mcp__decompile addr="<isallowed_func_addr>" |
| 50 | ``` |
| 51 | |
| 52 | Confirm `allow_func_addr` is the simple byte setter pattern: |
| 53 | |
| 54 | ```c |
| 55 | void __fastcall sub_18009B330(__int64 a1, char a2) |
| 56 | { |
| 57 | *(_BYTE *)(a1 + 1372) = a2; |
| 58 | } |
| 59 | ``` |
| 60 | |
| 61 | Windows assembly example: |
| 62 | |
| 63 | ```asm |
| 64 | mov [rcx+55Ch], dl |
| 65 | retn |
| 66 | ``` |
| 67 | |
| 68 | Then confirm `isallowed_func_addr` is the matching byte getter using the **same member offset**: |
| 69 | |
| 70 | ```c |
| 71 | __int64 __fastcall sub_18009B340(__int64 a1) |
| 72 | { |
| 73 | return *(unsigned __int8 *)(a1 + 1372); |
| 74 | } |
| 75 | ``` |
| 76 | |
| 77 | Windows assembly example: |
| 78 | |
| 79 | ```asm |
| 80 | movzx eax, byte ptr [rcx+55Ch] |
| 81 | retn |
| 82 | ``` |
| 83 | |
| 84 | The exact member offset may change across game updates. The identification rule is: |
| 85 | |
| 86 | 1. `allow_func_addr` writes one byte to `this + <member_offset>` (setter pattern) |
| 87 | 2. `isallowed_func_addr` is the next vtable entry (`allow_vfunc_index + 1`) |
| 88 | 3. The candidate reads and returns one unsigned byte from the **same** `this + <member_offset>` |
| 89 | |
| 90 | If both conditions hold, the candidates are `CNetworkMessages_AllowAdditionalMessageRegistration` and `CNetworkMessages_IsAdditionalMessageRegistrationAllowed`. |
| 91 | |
| 92 | ### 5. Generate Function Signatures |
| 93 | |
| 94 | **ALWAYS** Use SKILL `/generate-signature-for-function` with `addr=<allow_func_addr>` to generate a robust and unique `func_sig` for `CNetworkMessages_AllowAdditionalMessageRegistration`. |
| 95 | |
| 96 | **ALWAYS** Use SKILL `/generate-signature-for-function` with `addr=<isallowed_func_addr>` to generate a robust and unique `func_sig` for `CNetworkMessages_IsAdditionalMessageRegistrationAllowed`. |
| 97 | |
| 98 | Use the returned validated `func_sig` values in the next steps. |
| 99 | |
| 100 | ### 6. Write IDA Analysis Output as YAML for AllowAdditionalMessageRegistration |
| 101 | |
| 102 | **ALWAYS** Use SKILL `/write-vfunc-as-yaml` to write the analysis results. |
| 103 | |
| 104 | Required parameters: |
| 105 | - `func_name`: `CNetworkMessages_AllowAdditionalMessageRegistration` |
| 106 | - `func_addr`: `<allow_func_addr>` |
| 107 | - `func_sig`: The validated signature from step 5 |
| 108 | - `vfunc_sig`: `None` |
| 109 | |
| 110 | VTable parameters: |
| 111 | - `vtable_name`: `CNetworkMessages` |
| 112 | - `vfunc_offset`: `<allow_vfunc_offset>` in hex |
| 113 | - `vfunc_index`: `<allow_vfunc_index>` |
| 114 | |
| 115 | ### 7. Write IDA Analysis Output as YAML for IsAdditionalMessageRegistrationAllowed |
| 116 | |
| 117 | **ALWAYS** Use SKILL `/write-vfunc-as-yaml` to write the analysis results. |
| 118 | |
| 119 | Required parameters: |
| 120 | - `func_name`: |