Generate Function Signature

VerifiedSafe

Generate and validate unique byte signatures for functions using IDA Pro MCP. Reliably locate functions across binary updates with pattern-scanning signatures.

Sby Skills Guide Bot
SecurityAdvanced
7/25/2026
Claude CodeCursor
#reverse-engineering#ida-pro#binary-analysis#signatures#mcp

Recommended for

Automated summary

Automatically generates and validates a unique byte signature for a function analyzed in IDA Pro through the MCP server, detecting volatile operand bytes to wildcard.

Strengths

  • Fully automates wildcard detection by inspecting operand types (imm, near, far, mem, displ) and call/jump instruction patterns.
  • Resolves the supplied address to the real function start, even when the user points into the middle of the body.
  • Binary-searches for the shortest signature that remains unique in the binary, always stopping on complete instruction boundaries.
  • Handles IDA version differences by falling back from find_bytes to bin_search.

Limitations

  • Requires an IDA Pro instance with the ida-pro-mcp server connected and a function already recognized by analysis.
  • Signature validity is tied to the current binary and may no longer be unique after a major program update.
  • The provided script is an excerpt that must run via py_eval, so some familiarity with the IDAPython API is expected.
When to use it

Use this skill when you need a stable pattern signature to relocate a function across successive builds of a binary.

When not to use it

Skip it if you lack an IDA Pro environment with MCP active, or if you only need to rename or decompile a function.

Security analysis

Safe
Quality score88/100

The skill instructs the AI to run a Python script via IDA Pro MCP's py_eval to analyze binary functions and generate byte signatures. The script only reads binary bytes, resolves function boundaries, and performs pattern searches within the loaded IDA database. It does not execute destructive commands, access the network, exfiltrate data, or modify files. The use of py_eval is scoped to a specific, read-only analysis task.

No concerns found

How this analysis is made

Examples

Signature for a known function
Generate a unique byte signature for the function at 0x00401A30 so I can find it again in the next build of this DLL.
Signature from a mid-function address
I'm sitting at 0x14000F2C inside a function — produce the shortest unique pattern signature for the whole function and show me the wildcarded bytes.
Validate signature uniqueness
Create a pattern-scanning signature for this function and confirm it matches exactly one location in the binary.

name: generate-signature-for-function description: | 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 function

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" → Use func_sig directly as the final signature
  • status == "failed" → See Step 2

2. Iterate if Needed

If Step 1 returns status: "failed":

  1. Increase max_sig_bytes (e.g., to 192) and re-run Step 1
  2. Consider including bytes beyond the function boundary
  3. 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 ?? ?? ?? ??

From the file to a first result

The download contains exactly the content displayed on this page. This copy may differ from the latest version in the source repository.

View the source and supporting files

This download contains SKILL.md only. Any scripts, references, templates and dependencies are not included. Get the required files from the source, preserving their directory structure, before continuing.

1. Download the file

Download SKILL.md

From the root of a test project, save the file as .skill-downloads/generate-function-signature-mrzxurg0/SKILL.md, or use the command below. This folder is for inspecting the skill before installation.

Command for macOS/Linux or WSL: requires a POSIX shell and curl. On Windows without WSL, use the download button and create the folder manually.

mkdir -p '.skill-downloads/generate-function-signature-mrzxurg0' && curl --fail --show-error --location 'https://skills-guides.com/api/skills/generate-function-signature-mrzxurg0/download' --output '.skill-downloads/generate-function-signature-mrzxurg0/SKILL.md.part' && mv '.skill-downloads/generate-function-signature-mrzxurg0/SKILL.md.part' '.skill-downloads/generate-function-signature-mrzxurg0/SKILL.md'

2. Check prerequisites

Read SKILL.md before using it. If it references scripts or external services, inspect them and prepare the required access in your test environment.

Original excerpt: Prerequisites
  • Function address (from decompilation, xrefs, or rename)
  • IDA Pro MCP connection

The platforms on this page are catalog indications. The paths below follow tool documentation; they do not prove this skill has been run in those tools. No minimum tool version is confirmed for this listing.

3. Load the skill

After inspection, copy the complete folder into your project using one of the commands below, then open a new tool session. The command stops if a folder with the same name already exists: compare the files before replacing it.

Claude Code
test -f '.skill-downloads/generate-function-signature-mrzxurg0/SKILL.md' && test -s '.skill-downloads/generate-function-signature-mrzxurg0/SKILL.md' && mkdir -p '.claude/skills' && test ! -e '.claude/skills/generate-signature-for-function' && cp -R '.skill-downloads/generate-function-signature-mrzxurg0' '.claude/skills/generate-signature-for-function'

Cursor
test -f '.skill-downloads/generate-function-signature-mrzxurg0/SKILL.md' && test -s '.skill-downloads/generate-function-signature-mrzxurg0/SKILL.md' && mkdir -p '.cursor/skills' && test ! -e '.cursor/skills/generate-signature-for-function' && cp -R '.skill-downloads/generate-function-signature-mrzxurg0' '.cursor/skills/generate-signature-for-function'

OpenSkills

OpenSkills must already be installed. The local install/read procedure is checked with OpenSkills 1.5.0, which requires Node.js ≥ 20.6.0. Catalog slugs are not resolved automatically.

Official OpenSkills installation
openskills install './.skill-downloads/generate-function-signature-mrzxurg0'

openskills read 'generate-function-signature-mrzxurg0'

Reading should display the installed file content and its base directory. It does not run the skill or install its dependencies.

For an agent that reads AGENTS.md, then sync the index. This command changes AGENTS.md: review the diff before using it.

openskills sync

Manual method or another tool: attach SKILL.md to a conversation, or open it in an agent that can read files. Include any required supporting resources. No universal folder is recognized by every tool.

4. Try a first task

Use a short, synthetic input: an API endpoint, a small document or an interface brief. In a new conversation, attach the file or give the agent its path, then adapt this request:

Read .skill-downloads/generate-function-signature-mrzxurg0/SKILL.md and apply its instructions to this example: [describe a test input]. Identify any missing files, dependencies or access. Produce the result requested by the skill without inventing data or running unreviewed scripts.

Expected result: output matching the skill instructions, or a precise list of missing prerequisites. A read confirmation alone does not validate a first use. If an external resource is unavailable, that path remains untested.

Related skills