$npx -y skills add HLND2T/CS2_VibeSignatures --skill write-globalvar-as-yamlWrite global variable analysis results as YAML file beside the binary using IDA Pro MCP. Use this skill after completing global variable identification and signature generation to persist the results in a standardized YAML format.
| 1 | # Write Global Variable IDA Analysis Output as YAML |
| 2 | |
| 3 | Persist global variable analysis results to a YAML file beside the binary using IDA Pro MCP. |
| 4 | |
| 5 | ## Prerequisites |
| 6 | |
| 7 | Before using this skill, you should have: |
| 8 | 1. Identified and renamed the target global variable |
| 9 | 2. Generated a unique signature using `/generate-signature-for-globalvar` |
| 10 | |
| 11 | ## Required Parameters |
| 12 | |
| 13 | | Parameter | Description | Example | |
| 14 | |-----------|-------------|---------| |
| 15 | | `gv_name` | Name of the global variable | `IGameSystem_InitAllSystems_pFirst` | |
| 16 | | `gv_addr` | Virtual address of the global variable | `0x180XXXXXX` | |
| 17 | | `gv_sig` | Unique byte signature (must start at the GV-referencing instruction) | `48 8B 1D ?? ?? ?? ?? 48 85 DB 0F 84 ?? ?? ?? ?? BD FF FF 00 00` | |
| 18 | | `gv_inst_length` | Length of the instruction in bytes | `7` | |
| 19 | | `gv_inst_disp` | Displacement offset within the instruction | `3` | |
| 20 | | `gv_sig_va` | Virtual address where the signature matches | `0x180XXXXXX` | |
| 21 | |
| 22 | **Note:** `gv_inst_offset` is always 0 - the signature MUST start at the instruction that references the global variable. |
| 23 | |
| 24 | ## Method |
| 25 | |
| 26 | ```python |
| 27 | mcp__ida-pro-mcp__py_eval code=""" |
| 28 | import idaapi |
| 29 | import os |
| 30 | import yaml |
| 31 | |
| 32 | # === REQUIRED: Replace these values === |
| 33 | gv_name = "<gv_name>" # e.g., "IGameSystem_InitAllSystems_pFirst" |
| 34 | gv_addr = <gv_addr> # e.g., 0x180XXXXXX |
| 35 | gv_sig = "<gv_sig>" # e.g., "48 8B 1D ?? ?? ?? ?? 48 85 DB 0F 84 ?? ?? ?? ?? BD FF FF 00 00" |
| 36 | gv_sig_va = <gv_sig_va> # e.g., 0x180XXXXXX (virtual address where signature matches) |
| 37 | gv_inst_length = <gv_inst_length> # e.g., 7 (instruction length in bytes) |
| 38 | gv_inst_disp = <gv_inst_disp> # e.g., 3 (displacement offset within instruction) |
| 39 | # ====================================== |
| 40 | |
| 41 | # Fixed value - signature must start at the GV-referencing instruction |
| 42 | gv_inst_offset = 0 |
| 43 | |
| 44 | # Get binary path and determine platform |
| 45 | input_file = idaapi.get_input_file_path() |
| 46 | dir_path = os.path.dirname(input_file) |
| 47 | |
| 48 | if input_file.endswith('.dll'): |
| 49 | platform = 'windows' |
| 50 | image_base = idaapi.get_imagebase() |
| 51 | else: |
| 52 | platform = 'linux' |
| 53 | image_base = 0x0 |
| 54 | |
| 55 | gv_rva = gv_addr - image_base |
| 56 | |
| 57 | data = { |
| 58 | 'gv_name': gv_name, |
| 59 | 'gv_va': hex(gv_addr), |
| 60 | 'gv_rva': hex(gv_rva), |
| 61 | 'gv_sig': gv_sig, |
| 62 | 'gv_sig_va': hex(gv_sig_va), |
| 63 | 'gv_inst_offset': gv_inst_offset, |
| 64 | 'gv_inst_length': gv_inst_length, |
| 65 | 'gv_inst_disp': gv_inst_disp, |
| 66 | } |
| 67 | |
| 68 | yaml_path = os.path.join(dir_path, f"{gv_name}.{platform}.yaml") |
| 69 | with open(yaml_path, 'w', encoding='utf-8') as f: |
| 70 | yaml.dump(data, f, default_flow_style=False, sort_keys=False) |
| 71 | print(f"Written to: {yaml_path}") |
| 72 | """ |
| 73 | ``` |
| 74 | |
| 75 | ## Output File Naming Convention |
| 76 | |
| 77 | The output YAML filename follows this pattern: |
| 78 | - `<gv_name>.<platform>.yaml` |
| 79 | |
| 80 | Examples: |
| 81 | - `server.dll` → `IGameSystem_InitAllSystems_pFirst.windows.yaml` |
| 82 | - `libserver.so` / `libserver.so` → `IGameSystem_InitAllSystems_pFirst.linux.yaml` |
| 83 | |
| 84 | ## Output YAML Format |
| 85 | |
| 86 | ```yaml |
| 87 | gv_name: IGameSystem_InitAllSystems_pFirst |
| 88 | gv_va: 0x180XXXXXX # Global variable's virtual address - changes with game updates |
| 89 | gv_rva: 0xXXXXXX # Relative virtual address (VA - image base) - changes with game updates |
| 90 | gv_sig: 41 B8 80 00 00 00 48 8D 99 10 05 00 00 # Unique byte signature (starts at GV-referencing instruction) |
| 91 | gv_sig_va: 0x180XXXXXX # The virtual address that signature matches |
| 92 | gv_inst_offset: 0 # Always 0 - signature must start at the GV-referencing instruction |
| 93 | gv_inst_length: 7 # 48 8B 1D XX XX XX XX = 7 bytes |
| 94 | gv_inst_disp: 3 # Displacement offset start at position 3 (after 48 8B 1D) |
| 95 | ``` |
| 96 | |
| 97 | ## Platform Detection |
| 98 | |
| 99 | The skill automatically detects the platform based on file extension: |
| 100 | - `.dll` → Windows (uses `idaapi.get_imagebase()` for image base) |
| 101 | - `.so` → Linux (uses `0x0` as image base) |
| 102 | |
| 103 | ## Notes |
| 104 | |
| 105 | - All values marked "changes with game updates" should be regenerated when analyzing new binary versions |
| 106 | - The YAML file is written to the same directory as the input binary |
| 107 | - gv_rva is automatically calculated as `gv_va - image_base` |