بنقرة واحدة
binary-ninja-scripting
Write and execute Binary Ninja Python scripts — full API reference included
التثبيت باستخدام Codex أو Claude انسخ هذا Prompt والصقه في Codex أو Claude أو مساعد آخر ليراجع صفحة Skill ويثبّتها لك.
القائمة
Write and execute Binary Ninja Python scripts — full API reference included
التثبيت باستخدام Codex أو Claude انسخ هذا Prompt والصقه في Codex أو Claude أو مساعد آخر ليراجع صفحة Skill ويثبّتها لك.
استنادا إلى تصنيف SOC المهني
Patch binary code in Binary Ninja using natural language — read, assemble, write, verify
Patch binary code in IDA Pro using natural language — read, assemble, write, verify
Systematic binary deobfuscation — string decryption, control flow flattening (CFF) removal, opaque predicate elimination, mixed boolean-arithmetic (MBA) simplification, bogus control flow, instruction substitution reversal, dead code removal, and anti-disassembly fixes. Trigger: deobfuscate, unobfuscate, deobfuscation, CFF, flatten, opaque predicate, MBA, obfuscated, OLLVM, Tigress, VMProtect, string decryption, junk code, bogus control flow, instruction substitution, anti-disassembly
Write and execute IDAPython scripts — full API reference included
Expert ELF malware analysis — packing, toolchain ID, kill chain, persistence, C2, rootkits, cryptominers, Go/Rust/Mirai patterns, MITRE ATT&CK mapping
Modify binary behavior using natural language — explore, plan, patch, save
| name | Binary Ninja Scripting |
| description | Write and execute Binary Ninja Python scripts — full API reference included |
| tags | ["scripting","binja","python","automation"] |
| author | Rikugan |
| version | 1 |
Task: Help the user write Binary Ninja Python scripts. You have execute_python which runs code with bv (the current BinaryView), binaryninja module, and current_address pre-loaded.
print() for all output — it's captured and returned to you.None returns (e.g., bv.get_function_at() returns None if no function at that address).bv.update_analysis_and_wait() after bulk modifications (defining types, creating functions).define_user_*, add_user_*) persist to the database; auto types may be overwritten by analysis._user_ methods.The execute_python tool provides:
bv — the active BinaryViewbinaryninja — the full binaryninja modulebinaryninjaui — UI module (if available)current_address — cursor address (int, 0 if unavailable)data = bv.read(addr, length) # raw bytes
val = bv.read32(addr) # 32-bit int
ptr = bv.read_pointer(addr) # pointer-sized int
strings = bv.get_strings() # all StringReference objects
s = bv.get_string_at(addr) # single string
func = bv.get_function_at(addr) # exact start
funcs = bv.get_functions_containing(addr) # containing addr
funcs = bv.get_functions_by_name("main") # by name (list)
bv.add_user_function(addr) # create function
func.name = "NewName" # rename
func.type = Type.function(ret, params) # retype
func.set_comment_at(addr, "note") # comment
# Three levels: llil < mlil < hlil (prefer hlil for analysis)
for inst in func.hlil.instructions:
print(f"{hex(inst.address)}: {inst}")
# SSA form for data flow
defn = func.hlil.ssa_form.get_ssa_var_definition(ssa_var)
uses = func.hlil.ssa_form.get_ssa_var_uses(ssa_var)
# Navigate between levels
llil_inst = func.get_llil_at(addr)
hlil_from_llil = llil_inst.hlil
refs = bv.get_code_refs(addr) # code refs TO addr
refs = bv.get_data_refs(addr) # data refs TO addr
refs = bv.get_code_refs_from(addr) # code refs FROM addr
callers = func.callers # calling functions
callees = func.callees # called functions
from binaryninja import Type, StructureBuilder
# Primitives — ALWAYS use Type.* constructors, never raw strings
Type.int(4, True) # int32_t (signed=True default)
Type.int(4, False) # uint32_t
Type.int(8, False) # uint64_t
Type.int(2, False) # uint16_t
Type.int(1, False) # uint8_t
Type.char() # char (signed byte)
Type.void() # void
Type.bool() # bool
Type.float(4) # float
Type.float(8) # double
# Pointers
Type.pointer(bv.arch, Type.char()) # char*
Type.pointer(bv.arch, Type.void()) # void*
Type.pointer(bv.arch, Type.int(4, False)) # uint32_t*
# char** (pointer-to-pointer)
Type.pointer(bv.arch, Type.pointer(bv.arch, Type.char()))
# Arrays — NEVER use string syntax "uint8_t[256]", it will fail
Type.array(Type.int(1, False), 256) # uint8_t[256]
Type.array(Type.char(), 64) # char[64]
Type.array(Type.int(4, False), 8) # uint32_t[8]
from binaryninja import Type, StructureBuilder
# ✅ Correct — always use Type.* for field types, never strings
s = StructureBuilder.create()
s.append(Type.int(4, False), "a_type") # uint32_t a_type
s.append(Type.int(8, False), "a_val") # uint64_t a_val
s.append(Type.pointer(bv.arch, Type.char()), "name") # char* name
s.append(Type.array(Type.int(1, False), 16), "buf") # uint8_t buf[16]
bv.define_user_type("MyStruct", Type.structure_type(s))
# ❌ WRONG — string types silently fail (fields are dropped without error!)
s.append("uint32_t", "field") # SILENT DROP
s.append("uint8_t[16]", "buf") # PARSER ERROR or SILENT DROP
# Dependency order: define inner structs FIRST
s_inner = StructureBuilder.create()
s_inner.append(Type.int(4, False), "x")
s_inner.append(Type.int(4, False), "y")
bv.define_user_type("Entry", Type.structure_type(s_inner))
# Then reference with named_type_from_registered_type
s_outer = StructureBuilder.create()
entry_ref = Type.named_type_from_registered_type(bv, "Entry")
s_outer.append(entry_ref, "entry") # Entry entry
s_outer.append(Type.array(entry_ref, 32), "tbl") # Entry tbl[32]
bv.define_user_type("Table", Type.structure_type(s_outer))
# ALWAYS validate after defining — never assume it worked
t = bv.get_type_by_name("MyStruct")
if t is None:
print("ERROR: type not registered")
elif t.width == 0:
print("ERROR: empty struct — field types were likely rejected")
else:
print(f"OK: MyStruct, {t.width} bytes, {len(t.structure.members)} fields")
for m in t.structure.members:
print(f" +{m.offset:#x} {m.type} {m.name}")
# Apply to data
ntr = Type.named_type_from_registered_type(bv, "MyStruct")
bv.define_user_data_var(addr, ntr)
# Enum
Type.enumeration(members=[("VAL_A", 0), ("VAL_B", 1)])
# Parse C — only works for types BN already knows (platform types)
# DO NOT use this for custom/typedef types; define them via Type.* API instead
t, name = bv.parse_type_string("uint64_t*") # OK (platform type)
t, name = bv.parse_type_string("uint32_t") # may fail on some platforms
# If you must look up a type by C name, check it exists first
def resolve_type(bv, c_name: str):
"""Parse a C type name safely, return Type or None."""
try:
t, _ = bv.parse_type_string(c_name)
return t
except Exception:
return None
# Mapping common C names to Type.* constructors (use these instead)
TYPE_MAP = {
"uint8_t": Type.int(1, False),
"uint16_t": Type.int(2, False),
"uint32_t": Type.int(4, False),
"uint64_t": Type.int(8, False),
"int8_t": Type.int(1, True),
"int16_t": Type.int(2, True),
"int32_t": Type.int(4, True),
"int64_t": Type.int(8, True),
"size_t": Type.int(bv.arch.address_size, False),
"uintptr_t":Type.int(bv.arch.address_size, False),
"char": Type.char(),
"void": Type.void(),
}
from binaryninja import Symbol, SymbolType
sym = Symbol(SymbolType.DataSymbol, addr, "g_config")
bv.define_user_symbol(sym)
bv.get_symbol_at(addr)
bv.get_symbols_by_name("main")
for seg in bv.segments:
print(f"{hex(seg.start)}-{hex(seg.end)}")
for name, sec in bv.sections.items():
print(f"{name}: {hex(sec.start)}-{hex(sec.end)}")
bv.get_segment_at(addr)
bv.get_sections_at(addr)
from binaryninja.interaction import (
show_message_box, show_plain_text_report,
show_markdown_report, show_html_report,
get_text_line_input, get_int_input,
get_choice_input, get_address_input,
)
# Reports are the best way to show formatted output
show_markdown_report("Title", "# Results\n- item 1\n- item 2")
show_plain_text_report("Title", large_text_output)
# Find functions calling a specific import
target = bv.get_functions_by_name("CreateFileW")
if target:
for caller in target[0].callers:
print(f"{hex(caller.start)}: {caller.name}")
# Search for byte pattern
addr = bv.find_next_data(bv.start, b"\x48\x89\x5C\x24")
# Iterate all data variables
for addr, dv in bv.data_vars.items():
print(f"{hex(addr)}: {dv.type} = {dv.name or '(unnamed)'}")
# Bulk rename with evidence
for func in bv.functions:
if func.name.startswith("sub_"):
hlil = func.hlil_if_available
if hlil:
for inst in hlil.instructions:
# ... analyze and rename based on evidence
pass
# Background task for long operations
from binaryninja import BackgroundTaskThread
class MyTask(BackgroundTaskThread):
def __init__(self, bv):
super().__init__("Processing...", can_cancel=True)
self.bv = bv
def run(self):
for i, func in enumerate(self.bv.functions):
if self.cancelled:
break
self.progress = f"{func.name} ({i}/{len(self.bv.functions)})"
Binary Ninja supports IL-level modifications through its workflow system and replace_expr API.
# Replace an IL expression with a new one
# Works at LLIL and MLIL levels
il_func = analysis_context.llil # or .mlil
expr = il_func[index]
new_expr = il_func.const(expr.size, value)
il_func.replace_expr(expr, new_expr)
il_func.finalize()
il_func.generate_ssa_form()
# Rebuild a function with structural changes (block reordering, removal)
il_func.prepare_to_copy_function(src_func)
for block in src_blocks:
il_func.prepare_to_copy_block(block)
for instr in block:
il_func.append(instr.copy_to(il_func))
il_func.copy_to(block)
il_func.finalize()
il_func.generate_ssa_form()
# Register a transform at a specific pipeline stage
from binaryninja import Workflow, Activity
workflow = Workflow("core.function.metaAnalysis").clone("MyWorkflow")
activity = Activity("myTransform", action=my_transform_func)
workflow.register_activity(activity)
workflow.insert_after("core.function.generateMediumLevelIL", "myTransform")
workflow.register()
core.function.generateMediumLevelIL — modify LLIL before MLIL generationcore.function.generateMediumLevelIL — modify MLIL after generationAnalysisContext during workflow activitiesfinalize() + generate_ssa_form() after modifications# Create labels for control flow changes
label = il_func.get_label_for_address(il_func.arch, target_addr)
il_func.append(il_func.goto(label))
func.hlil_if_available returns None if HLIL hasn't been generated yet — safer than func.hlil which may block.bv.functions returns a snapshot list — safe to iterate while modifying.Type.named_type_from_registered_type(bv, name) to reference a type you've defined, not the raw Type object._user_ methods persist; _auto_ methods may be overwritten by re-analysis.