Creates persistent, pattern-scannable byte signatures for functions using IDA Pro to ensure stability across binary updates.
Install
mkdir -p .claude/skills/generate-signature-for-function && curl -L -o skill.zip "https://agentskills.codes/api/skills/download/13409" && unzip -o skill.zip -d .claude/skills/generate-signature-for-function && rm skill.zipInstalls to .claude/skills/generate-signature-for-function
Activation
This is the description your AI agent reads to decide when to run this skill — the better it matches your request, the more reliably it fires.
Generate and validate unique byte signatures for functions using IDA Pro MCP. Use this skill when you need to create a pattern-scanning signature for a function that can reliably locate it across binary updates. Triggers: generate signature, byte signature, pattern signature, function signature, unique signature, sig for functionKey capabilities
- →Generate unique hex byte signatures for functions
- →Programmatically detect wildcards in signatures
- →Validate signature uniqueness through progressive testing
- →Resolve input addresses to actual function starts
- →Output the shortest unique signature directly
How it works
The skill resolves the input address to the function start, decodes instructions, programmatically determines wildcard positions, and progressively tests at each instruction boundary via binary search to output the shortest unique signature.
Inputs & outputs
When to use generate-signature-for-function
- →Create function signature
- →Verify signature uniqueness
- →Prepare pattern scan for binary update
About this skill
Generate Signature for Function
Generate a unique hex byte signature for a function using fully programmatic wildcard detection and validation — no manual byte analysis required.
Prerequisites
- Function address (from decompilation, xrefs, or rename)
- IDA Pro MCP connection
Method
1. Generate and Validate Signature (Single Step)
Use a single py_eval call that:
- Resolves the input address to the actual function start
- Decodes instructions and programmatically determines wildcard positions
- Tracks instruction boundaries so prefixes always cover complete instructions
- Progressively tests at each instruction boundary via binary search
- Outputs the shortest unique signature directly
Note: The input address may be in the middle of a function. The script automatically resolves it to the actual function start.
mcp__ida-pro-mcp__py_eval code="""
import idaapi, ida_bytes, idautils, ida_ua, ida_segment, json
input_addr = <func_addr>
min_sig_bytes = 6
max_sig_bytes = 96
max_instructions = 64
# --- Binary search wrapper (IDA 9.0+ find_bytes -> older bin_search fallback) ---
def raw_bin_search(ea, max_ea, data, mask, flags=0):
if hasattr(ida_bytes, 'find_bytes'):
return ida_bytes.find_bytes(data, ea, range_end=max_ea, mask=mask, flags=flags)
return ida_bytes.bin_search(ea, max_ea, data, mask, len(data), flags)
# --- Resolve to actual function start ---
func = idaapi.get_func(input_addr)
if not func:
print(json.dumps({"error": f"{hex(input_addr)} is not inside a known function", "status": "failed"}))
raise SystemExit
func_addr = func.start_ea
if func_addr != input_addr:
print(f"NOTE: Resolved {hex(input_addr)} -> function start at {hex(func_addr)}")
# --- Collect instruction bytes with auto-wildcarding ---
limit_end = min(func.end_ea, func_addr + max_sig_bytes)
sig_tokens = []
inst_boundaries = [] # cumulative byte count at end of each instruction
cursor = func_addr
while cursor < func.end_ea and cursor < limit_end and len(sig_tokens) < max_sig_bytes:
insn = idautils.DecodeInstruction(cursor)
if not insn or insn.size <= 0:
break
raw = ida_bytes.get_bytes(cursor, insn.size)
if not raw:
break
wild = set()
# Auto-wildcard volatile operand bytes (imm/near/far/mem/displ)
for op in insn.ops:
op_type = int(op.type)
if op_type == int(idaapi.o_void):
continue
if op_type in (int(idaapi.o_imm), int(idaapi.o_near), int(idaapi.o_far), int(idaapi.o_mem), int(idaapi.o_displ)):
offb = int(op.offb)
if offb > 0 and offb < insn.size:
dsz = ida_ua.get_dtype_size(getattr(op, 'dtype', getattr(op, 'dtyp', 0)))
if dsz <= 0:
dsz = insn.size - offb
end = min(insn.size, offb + dsz)
for i in range(offb, end):
wild.add(i)
offo = int(op.offo)
if offo > 0 and offo < insn.size:
dsz2 = ida_ua.get_dtype_size(getattr(op, 'dtype', getattr(op, 'dtyp', 0)))
if dsz2 <= 0:
dsz2 = insn.size - offo
end2 = min(insn.size, offo + dsz2)
for i in range(offo, end2):
wild.add(i)
# Special handling for call/jump instructions
b0 = raw[0]
if b0 in (0xE8, 0xE9, 0xEB):
for i in range(1, insn.size):
wild.add(i)
elif b0 == 0x0F and insn.size >= 2 and (raw[1] & 0xF0) == 0x80:
for i in range(2, insn.size):
wild.add(i)
elif 0x70 <= b0 <= 0x7F:
for i in range(1, insn.size):
wild.add(i)
for idx in range(insn.size):
sig_tokens.append("??" if idx in wild else f"{raw[idx]:02X}")
inst_boundaries.append(len(sig_tokens))
cursor += insn.size
if not sig_tokens:
print(json.dumps({"error": f"no instruction bytes at {hex(func_addr)}", "status": "failed"}))
raise SystemExit
# --- Search bounds ---
seg = ida_segment.get_segm_by_name(".text")
if seg:
search_start, search_end = seg.start_ea, seg.end_ea
else:
search_start, search_end = idaapi.cvar.inf.min_ea, idaapi.cvar.inf.max_ea
# --- Progressive search at instruction boundaries only ---
best_sig = None
for boundary in inst_boundaries:
if boundary < min_sig_bytes:
continue
prefix_tokens = sig_tokens[:boundary]
if all(t == "??" for t in prefix_tokens):
continue
data = bytes(0 if t == "??" else int(t, 16) for t in prefix_tokens)
mask = bytes(0x00 if t == "??" else 0xFF for t in prefix_tokens)
flags = ida_bytes.BIN_SEARCH_FORWARD | ida_bytes.BIN_SEARCH_NOBREAK
matches = []
ea = raw_bin_search(search_start, search_end, data, mask, flags)
while ea != idaapi.BADADDR and len(matches) < 2:
matches.append(ea)
ea = raw_bin_search(ea + 1, search_end, data, mask, flags)
if len(matches) == 1 and matches[0] == func_addr:
best_sig = " ".join(prefix_tokens)
break
if best_sig:
print(json.dumps({
"func_va": hex(func_addr),
"func_rva": hex(func_addr - idaapi.get_imagebase()),
"func_size": hex(func.end_ea - func_addr),
"func_sig": best_sig,
"sig_bytes": len(best_sig.split()),
"status": "success"
}))
else:
print(json.dumps({
"func_va": hex(func_addr),
"func_size": hex(func.end_ea - func_addr),
"total_tokens": len(sig_tokens),
"sig_full": " ".join(sig_tokens),
"error": "no unique prefix found within collected bytes",
"status": "failed"
}))
"""
Result handling:
status == "success"→ Usefunc_sigdirectly as the final signaturestatus == "failed"→ See Step 2
2. Iterate if Needed
If Step 1 returns status: "failed":
- Increase
max_sig_bytes(e.g., to 192) and re-run Step 1 - Consider including bytes beyond the function boundary
- Re-run until unique
3. Continue with Unfinished Tasks
If we are called by a task from a task list / parent SKILL, restore and continue with the unfinished tasks.
Output Format
Signature format: space-separated hex bytes with ?? for wildcards.
Example: 48 89 5C 24 ?? 48 89 74 24 ?? 57 48 83 EC ?? 48 8B F9 E8 ?? ?? ?? ??
When not to use it
- →When manual byte analysis is preferred over programmatic wildcard detection
- →When IDA Pro MCP connection is not available
- →When the function address is unknown
Prerequisites
Limitations
- →Requires an IDA Pro MCP connection.
- →Requires a known function address.
- →If no unique prefix is found within collected bytes, it reports an error.
How it compares
This skill automates wildcard detection and validation, eliminating manual byte analysis and progressively testing for uniqueness, unlike manual signature creation.
Compared to similar skills
generate-signature-for-function side by side with the closest alternatives in the catalog.
| Skill | Installs | Updated | Safety | Difficulty |
|---|---|---|---|---|
| generate-signature-for-function (this skill) | 0 | 4mo | No flags | Intermediate |
| game-engine-resources | 14 | 4mo | No flags | Advanced |
| graphics-api-hooking | 7 | 2mo | No flags | Advanced |
| idapython | 4 | 7mo | No flags | Advanced |
Try saying
Example prompts that trigger this skill in your AI assistant.
You might also like
game-engine-resources
gmh5225
Guide for game engine development resources including engine source code, plugins, and development guides. Use this skill when researching game engines (Unreal, Unity, Godot, custom engines), engine architecture, or game development frameworks.
graphics-api-hooking
gmh5225
Guide for graphics API hooking and rendering techniques for DirectX, OpenGL, and Vulkan. Use this skill when working with graphics hooks, overlay rendering, shader manipulation, or game rendering pipeline analysis.
idapython
mrexodia
IDA Pro Python scripting for reverse engineering. Use when writing IDAPython scripts, analyzing binaries, working with IDA's API for disassembly, decompilation (Hex-Rays), type systems, cross-references, functions, segments, or any IDA database manipulation. Covers ida_* modules (50+), idautils iterators, and common patterns.
static-analysis
gmh5225
Expertise in LLVM-based static analysis including dataflow analysis, pointer analysis, taint tracking, and program verification. Use this skill when implementing security scanners, bug finders, code quality tools, or performing program analysis research.
memory-safety-patterns
sickn33
Implement memory-safe programming with RAII, ownership, smart pointers, and resource management across Rust, C++, and C. Use when writing safe systems code, managing resources, or preventing memory bugs.
libfuzzer
trailofbits
Coverage-guided fuzzer built into LLVM for C/C++ projects. Use for fuzzing C/C++ code that can be compiled with Clang.