BNMF Reference¶
Binary Ninja Modification Format (BNMF) is the declarative JSON protocol Sidekick uses to write changes back to the Binary Ninja database. Instead of issuing imperative commands, you describe the desired state of an object. The processor reads the current state, computes the delta, and applies the minimum changes needed.
BNMF is used internally by Sidekick's AI agents whenever they rename functions, define types, annotate code, or perform any other database modification. BNMF is submitted through the update_database tool.
For a conceptual overview of how modifications fit into the analysis workflow, see Editing Binaries with Suggestions.
Request Structure¶
A BNMF request is a JSON object with a human-readable description and a list of per-view change sets.
{
"description": "Human-readable summary of the change set",
"binary_view_changes": [
{
"modifications": [
{"uri": "bv:function/0x401000", "state": {"name": "process_input"}}
]
}
]
}
Request fields¶
| Field | Type | Default | Description |
|---|---|---|---|
description |
String | Required | Human-readable summary of the change set; recorded as the transaction's description in the Sidekick Transaction Log |
binary_view_changes |
Array[Object] | Required | Per-view change sets (see below) |
options.return_sample |
Integer (0–100) | 10 |
Number of sample modifications to include in the result |
Change set fields¶
| Field | Type | Default | Description |
|---|---|---|---|
binary_view_id |
String | None | Binary view to modify. Optional when the target has a single binary view (a missing or unknown ID is then replaced by that view). When several views are open (a project, or a file with a mapped view), name the view explicitly with the ID from the binary view list (Mach-O, or <project-file-id>/Mach-O in a project): a change set without binary_view_id is skipped with a warning, and if no change set remains the request is rejected with a list of the available view IDs |
modifications |
Array[Modification] | Required | Modifications to apply |
Modifications from all change sets that target the same binary view are applied together as one batch. Malformed change sets or modifications are skipped and reported in the result warnings. If you omit a modification id, one is assigned automatically (mod_0, mod_1, ...).
Modification fields¶
| Field | Type | Default | Description |
|---|---|---|---|
uri |
String | Required | Target object identifier |
state |
Object | null | Required | Desired state; null deletes the object |
id |
String | None | Client-assigned ID for dependency references |
depends_on |
Array[String] | None | IDs of modifications that must succeed first |
expect |
Object | None | Preconditions to validate before applying |
Atomic Processing¶
All modifications for a given binary view succeed or none of that view's changes are applied. If any modification fails, that view's batch is rolled back using Binary Ninja's undo system and the update fails with Failed to apply N modification(s): <uri>: <error>. When one update targets several binary views, the views are applied one after another. Views processed before the failing one keep their changes in the database, even though the transaction is reported as failed; the failing view and any later views are not applied.
There is no mode that keeps the successful part of a failed batch. To make partial progress, split the work into smaller updates.
Dependency Ordering¶
Use id and depends_on to enforce ordering when one modification must precede another — for example, defining a type before using it.
{
"modifications": [
{
"id": "def_type",
"uri": "bv:type/Buffer",
"state": {"definition": "struct Buffer { char* data; size_t len; }"}
},
{
"uri": "bv:function/0x401000/variable/arg1",
"state": {"type": "struct Buffer*"},
"depends_on": ["def_type"]
}
]
}
Rules:
- Modifications run in the order listed, except that each one runs after everything it depends on. A modification listed ahead of a prerequisite moves back only as far as that prerequisite.
- Only a modification that others depend on needs an id. A modification without an id can still use depends_on.
- If a modification fails, all modifications that depend on it (directly or transitively) are skipped.
- Duplicate id values, unknown dependency IDs, and circular dependencies all raise an error and fail the entire batch.
Preconditions (expect)¶
The expect field validates the current state before applying a modification. If validation fails, the modification fails with an ExpectationError, reported as Expectation failed: <uri>.<property>: expected 'X', got 'Y' for a property mismatch, or Expectation failed: Expected <uri> to exist / Expected <uri> to NOT exist for $exists checks.
$exists operator¶
{"expect": {"$exists": true}} // Entity must already exist
{"expect": {"$exists": false}} // Entity must NOT exist
An empty expect object ({}) requires the entity to exist without constraining any property values.
Property matching¶
Multiple properties can be checked simultaneously. All must match.
Collection Operators¶
For array-valued properties, use $add and $remove to make targeted changes without replacing the entire list.
{
"uri": "bv:component/NetworkSubsystem",
"state": {
"functions": {
"$add": ["0x401500"],
"$remove": ["0x401100"]
}
}
}
Collection operators are supported on functions and datavars (Component), indirect_branches and code_refs (Function Instruction), and parameters (Function). Function parameters are updated by position only — see the Function notes.
Processing order: $remove is applied first, then $add. $add deduplicates — adding an item that already exists is a no-op.
URI Reference¶
All URIs use the bv: scheme. Addresses are always in hexadecimal with a 0x prefix.
Summary table¶
| URI Pattern | Description |
|---|---|
bv:comment/{address} |
Global address comment, independent of functions |
bv:type/{name} |
Named type definition |
bv:type/{type_name}/member/{member_id} |
Struct or union member, or enum member (enum members are addressed by name) |
bv:datavar/{address} |
Data variable |
bv:function/{address} |
Function |
bv:function/{address}/instruction/{instr_addr} |
Instruction within a function |
bv:function/{address}/instruction/{instr_addr}/integer/{value}/{operand} |
Integer operand display type |
bv:function/{address}/variable/{var_name} |
Local variable within a function |
bv:function/{address}/block/{block_addr} |
Basic block highlight |
bv:function/{address}/uservalue/{def_site}/{var_name} |
User-informed value for a variable before or after an instruction |
bv:function/{address}/uservalues |
All user-informed variable values in a function |
bv:dataref/{from_addr}/{to_addr} |
User-defined data cross-reference |
bv:pointer |
Global pointer override |
bv:memory/{address} |
Raw bytes at an address |
bv:symbol/{address}/{symbol_type} |
Named symbol |
bv:section/{name} |
Memory section |
bv:segment/{address} |
Memory segment |
bv:region/{name} |
Named memory-map overlay region |
bv:tag/{address}/{type_name} |
Tag at an address |
bv:tagtype/{name} |
Tag type definition |
bv:library/{name} |
External library |
bv:external/{library}/{source_address} |
External symbol location |
bv:import/{address} |
Imported function signature (IAT slot / GOT entry) |
bv:component/{component_id} |
Component (function/data grouping) |
bv:stack/{function_address}/variable/{offset} |
Stack variable |
bv:stack/{function_address}/call_adjustment/{instruction_address} |
Per-call stack adjustment |
bv:stack/{function_address}/return_adjustment |
Function return stack adjustment |
Handler Reference¶
Comment — bv:comment/{address}¶
| Property | Type | Read | Write | Notes |
|---|---|---|---|---|
text |
String | Yes | Yes | Comment text |
- An address without a comment has no comment entity. In
expect,{"$exists": false}and{"text": ""}mean the same thing. state: nullremoves the comment;{"text": ""}and{"text": null}do the same.- This route reads and writes the global address comment, even inside a function. It survives function removal. Use a function's
commentproperty for its summary, orbv:function/{address}/instruction/{instr_addr}for a code-site comment belonging to that function./view/commentenumerates only global comments.
{"uri": "bv:comment/0x500000", "state": {"text": "Configuration blob: version byte followed by length-prefixed records"}}
Type — bv:type/{name}¶
| Property | Type | Read | Write | Notes |
|---|---|---|---|---|
name |
String | Yes | Yes | Rename by setting name to a new value |
definition |
String | Yes | Yes | Full C-syntax type definition |
state: nullundefines the type (undefine_user_type).- Namespace qualifiers (
::) in type strings are automatically wrapped in backticks if needed. - The URI takes the bare type name (no
struct/union/enumkeyword).bv:type/struct tableis accepted astablewhen the definition declares the same type. - A struct, union, class, or enum definition must be a direct named definition whose name matches the URI (
bv:type/Foowithstruct Foo { ... }). Anonymous aggregates and typedef wrappers such astypedef struct Foo {...} Bar;are rejected. - Derived types can use
__base(BaseName, offset)attributes. Each base type must already be defined (define it first and useid/depends_on), or the change fails withBase type '...' is not defined in the binary view. Define it before the derived type. - After applying, Sidekick compares the resulting type with the requested definition and fails the modification if the layout, base types, or members differ.
Type Member — bv:type/{type_name}/member/{member_id}¶
Works on struct, union, and enum types. Enum members are described in Enum members below.
For struct and union types, member_id formats are:
- Hex offset: 0x8, 0x10
- Decimal offset: 8, 16
- Member name: fieldName
| Property | Type | Read | Write | Notes |
|---|---|---|---|---|
name |
String | Yes | Yes | Member name |
type |
String | Yes | Yes | Member type string |
offset |
Integer | Yes | Yes | Byte offset in the structure |
- Adding a new member requires
typeand an offset, taken from a numericmember_idor fromoffset. - Changing
offsetremoves the member and re-inserts it at the new position. state: nullremoves the member from the structure.- Union limitation: For unions all members share offset 0, so address-based lookup returns the first match. Use member name as the
member_idto target a specific union member.
Enum members¶
The parent enum must already exist (define it first with bv:type/{name}, using id/depends_on for ordering). Enum members are addressed by name only; numeric member_id values are rejected.
| Property | Type | Read | Write | Notes |
|---|---|---|---|---|
name |
String | Yes | Yes | Rename the member; renaming to an existing member name is rejected |
value |
Integer or String | Yes | Yes | Integer, or a decimal/hex integer string such as "-0x1". Required when adding a member; must fit the enum's width and signedness |
state: nulldeletes the member. Deleting a missing member is a no-op.- Other members keep their effective values: implicitly numbered members that follow an edited or removed member become explicit.
- Different member names may share the same value.
{"uri": "bv:type/Status/member/STATUS_TIMEOUT", "expect": {"$exists": false}, "state": {"value": 3}}
Data Variable — bv:datavar/{address}¶
| Property | Type | Read | Write | Notes |
|---|---|---|---|---|
name |
String | Yes | Yes | Symbol name; empty string means unnamed |
type |
String | Yes | Yes | Type string; required when creating |
confidence |
Integer | Yes | Yes | Binary Ninja type confidence (0–255) attached to type; omit on write for the default (maximum) |
comment |
String | Yes | Yes | Comment at this address |
state: nullundefines the variable, removing both any user definition and any underlying analysis-generated definition. Removed analysis-generated definitions are blocked from being recreated by analysis. Deleting a missing variable is a no-op.- Supply
typewhen creating a data variable. If onlynameis given for an address with no data variable, a placeholdervoid-typed variable is created with that name.commentis stored at the address even when no data variable is defined. confidencemust be sent together withtypein the same modification; sendingconfidencealone is rejected withUnknown attributes for <uri>: confidence. It is attached to the parsed type viaType.with_confidence(...)before assignment. Use a lower value (e.g.128) to mark an AI-suggested type as "soft" so subsequent analysis can still refine it; omit the field (or use255) to pin a user-confident type that analysis will not override.
Function — bv:function/{address}¶
| Property | Type | Read | Write | Notes |
|---|---|---|---|---|
name |
String | Yes | Yes | Function name |
type |
String | Yes | Yes | Full function type signature. Reads leave out a __pure that analysis inferred; one you wrote is kept |
comment |
String | Yes | Yes | Function-level comment |
return_type |
String | Yes | Yes | Return type only |
calling_convention |
String | Yes | Yes | e.g. "cdecl", "stdcall" (case-insensitive) |
inline |
Boolean | Yes | Yes | Mark function as inline during analysis |
analysis_skipped |
Boolean | Yes | Yes | Skip analysis for this function |
can_return |
Boolean | Yes | Yes | Whether the function can return |
clobbered_regs |
Array[String] | Yes | Yes | Register names clobbered by the function; null reverts to auto-detected |
parameters |
Array[Object] | Yes | Yes | [{"name": "buf", "type": "char*"}, ...]. Renames or retypes the existing parameters by position; it cannot add or remove parameters, and entries past the current parameter count are ignored. To change the parameter count, set type with the full signature |
state: nullremoves the user-defined function (remove_user_function).state: {}creates a function at the address (create_user_function).- Invalid register names in
clobbered_regsraise an error with examples of valid names. - The function signature itself has no
confidencefield: Binary Ninja'sBNSetFunctionUserTypestores user function types at maximum confidence and provides no confidence parameter, so any confidence on the parsed type would be silently dropped. If you need a soft type, apply it to individual arguments viabv:function/{address}/variable/{var_name}withconfidence, or set the data variable at a global's address viabv:datavar/{address}.
Function Instruction — bv:function/{address}/instruction/{instr_addr}¶
| Property | Type | Read | Write | Notes |
|---|---|---|---|---|
comment |
String | Yes | Yes | Instruction-level comment |
highlight |
String | Yes | Yes | Color name: blue, red, green, cyan, magenta, yellow, orange, white, black; null clears the highlight |
goto_label |
String | No | Yes | Label name for jump target (requires HLIL). An edit that sets it cannot be reverted |
call_type |
String | Yes | Yes | Call type override; must be a function type such as int64_t(void*, int16_t*), not a pointer-to-function type; null removes the override |
stack_adjustment |
Integer | Yes | Yes | Stack adjustment override at this call site; reads null when there is none. null removes the override, so analysis derives the adjustment from the call type |
reg_stack_adjustment |
Object | Yes | Yes | Register stack names mapped to adjustment overrides, e.g. {"x87": 1}; reads {} when there are none. null removes the overrides |
indirect_branches |
Array | Yes | Yes | Target addresses for indirect branches (integers or hex strings; reads return hex strings). Each target must be a function start or lie in an executable segment; null clears user-defined branches |
code_refs |
Array | No | Yes | Addresses to add as user code cross-references. An edit that adds them cannot be reverted |
state: nullclears the comment and highlight.- The instruction's comment belongs to the function in the URI and is separate from any global comment at the same address. Function and instruction query results include their comments when set; instruction results also include
call_typewhen the call site has an override. Call overrides reflect completed analysis, so provisional results may still show the previous values. Within one batch, a later modification of the same call site sees the values written earlier in that batch. indirect_branchestakes raw addresses:["0x100000e58", "0x100000eb8"]. Do not use symbol names or(arch, address)tuples.
{
"uri": "bv:function/0x401200/instruction/0x401210",
"state": {"highlight": "yellow", "comment": "Round key XOR"}
}
Function Instruction Integer — bv:function/{address}/instruction/{instr_addr}/integer/{value}/{operand}¶
| Property | Type | Read | Write | Notes |
|---|---|---|---|---|
display_type |
String | Yes | Yes | Integer display type name without the DisplayType suffix: Binary, SignedOctal, UnsignedOctal, SignedDecimal, UnsignedDecimal, SignedHexadecimal, UnsignedHexadecimal, CharacterConstant, Pointer, Float, Double, Enumeration. Newer Binary Ninja builds also provide InvertedCharacterConstant, UnsignedComplementDecimal, and UnsignedComplementHexadecimal. The object exists only while a display type other than the default is chosen; state: null returns the integer to the default |
operand is a zero-based index that disambiguates when the same integer value appears multiple times in an instruction.
{
"uri": "bv:function/0x401000/instruction/0x401005/integer/0x100/0",
"state": {"display_type": "UnsignedDecimal"}
}
Function Variable — bv:function/{address}/variable/{var_name}¶
| Property | Type | Read | Write | Notes |
|---|---|---|---|---|
name |
String | Yes | Yes | Variable name |
type |
String | Yes | Yes | Variable type |
confidence |
Integer | Yes | Yes | Binary Ninja type confidence (0–255) attached to type; omit on write for the default (maximum) |
dead_store_elimination |
Boolean | Yes | Yes | true allows dead store elimination and false prevents it; null is the default, where analysis decides |
merge_from |
Array[String] | No | Yes | Variable names to merge into this one |
- A variable cannot be deleted.
state: nullremoves the name, type and dead store setting you gave it, so analysis decides them again; it does nothing to a variable you have not changed. - Reverting a rename or retype of a variable analysis had named and typed removes your definition rather than writing the old values back.
- The variable must already exist.
- To inform a variable's value at an instruction, use
bv:function/{address}/uservalue/{def_site}/{var_name}(see User Value below). confidencemust be sent together withtypein the same modification; sendingconfidencealone is rejected withUnknown attributes for <uri>: confidence. It is attached to the parsed type viaType.with_confidence(...)before the underlyingcreate_user_varcall. Use a lower value to mark an AI-suggested type as "soft" so subsequent analysis can still refine it; omit the field (or use255) to pin a user-confident type.merge_fromcombines the listed source variables into the target usingfunc.merge_vars. Source names that do not exist are silently skipped. A merge cannot be reverted.
{
"uri": "bv:function/0x406ec0/variable/arg1",
"state": {"type": "struct Connection*", "confidence": 128}
}
Function Block — bv:function/{address}/block/{block_addr}¶
| Property | Type | Read | Write | Notes |
|---|---|---|---|---|
color |
String | Yes | Yes | Block highlight color name: blue, green, cyan, red, magenta, yellow, orange, white, black ; null or state: null clears it. A custom (non-standard) color reads as null |
Block lookup is scoped to the specific function, so the same address in multiple functions is unambiguous.
User Value — bv:function/{address}/uservalue/{def_site}/{var_name}¶
Informs analysis of a variable's value at an instruction, influencing constant propagation, branch resolution, and type inference. def_site is the hex address of an instruction inside the function. By default the value applies after that instruction; append :before (0x401010:before) to inform the value before it instead. 0x401010:after is also accepted. The before and after values at one instruction are independent resources. The variable is looked up by name.
| Property | Type | Read | Write | Notes |
|---|---|---|---|---|
value |
Integer or Object | Yes | Yes | An integer constant, or one of the value sets below; null clears the user value |
size |
Integer | Yes | No | Variable width in bytes |
Value sets are objects with a kind. Integers anywhere in them may be decimal or hex strings.
kind |
Fields | Meaning |
|---|---|---|
constant |
value |
Same as a plain integer |
constant_ptr |
value |
A constant pointer |
stack_frame_offset |
offset |
An address at this offset in the function's stack frame |
signed_range / unsigned_range |
ranges: list of {start, end, step} |
Values within the ranges; step defaults to 1 |
in_set |
values |
One of the listed values |
not_in_set |
values |
Any value except those listed |
undetermined |
— | Explicitly unknown |
- The resource exists only while a user value is set at that site, so
expect: {"$exists": false}(or{"value": null}) keeps a write from replacing an existing value. state: null(or{"value": null}) clears the user value at that site, including values at instructions that are not definitions of the variable.- Reads report the canonical form: a constant as a plain integer, sets sorted, and every range
stepexplicit.expectcomparisons accept any equivalent spelling.
{
"uri": "bv:function/0x401000/uservalue/0x401050:before/var_14",
"expect": {"$exists": false},
"state": {"value": {"kind": "in_set", "values": [3, 7]}}
}
User Values — bv:function/{address}/uservalues¶
Every user-informed variable value in the function. The resource is absent when the function has none.
| Property | Type | Read | Write | Notes |
|---|---|---|---|---|
entries |
Array | Yes | Yes | {def_site, var, value} objects; def_site and var are the segments of the matching User Value URI. Writing replaces all of the function's user values |
count |
Integer | Yes | No | Number of entries |
- The resource exists only while the function has a user value; in
expect,{"entries": []}means the same as{"$exists": false}. state: null(or{"entries": []}) clears every user value in the function.
{
"uri": "bv:function/0x401000/uservalues",
"state": {"entries": [
{"def_site": "0x401010", "var": "arg1", "value": 0},
{"def_site": "0x401050:before", "var": "var_14", "value": {"kind": "in_set", "values": [3, 7]}}
]}
}
Data Reference — bv:dataref/{from_addr}/{to_addr}¶
No properties — this is an existence-only resource.
state: {}creates the reference (add_user_data_ref).state: nullremoves the reference (remove_user_data_ref).
Pointer — bv:pointer¶
| Property | Type | Read | Write | Notes |
|---|---|---|---|---|
value |
Integer | Yes | Yes | The global pointer address the override sets (binary-wide); null is an override of Undetermined |
Analysis works out the global pointer by itself. This object is your override of that result and exists only while one is set, so expect: {"$exists": false} matches a view that has none.
- Writing
valuesets the override;{"value": null}forces the pointer toUndetermined. state: nullremoves the override, so analysis decides the value again.- Setting, changing and removing an override each revert exactly.
- A write fails on a platform that has no global pointer register (for example x86-64 or AArch64).
Memory — bv:memory/{address}¶
| Property | Type | Read | Write | Notes |
|---|---|---|---|---|
bytes |
Hex String | No | Yes | Raw bytes to write, e.g. "90909090" |
expect |
Hex String | No | Yes | Expected current bytes (compare-and-swap) |
state: nullraises an error — memory cannot be deleted.- When
expectis provided, the write only proceeds if the current bytes at the address match. Use this to avoid overwriting bytes that have already changed. - If
expectandbyteshave different lengths, bytes are inserted or removed to fit (growing or shrinking the data, which shifts the following bytes). Only a Raw view can change length; in any other view a length-changing patch fails and nothing is written. With noexpect, the bytes are overwritten in place. - A patch fails if Binary Ninja cannot write every byte, for example when the range is not backed by file data (such as
.bss). - A top-level
"expect": {"bytes": "7401"}precondition works as an equivalent guard.
Symbol — bv:symbol/{address}/{symbol_type}¶
symbol_type is any Binary Ninja SymbolType name: FunctionSymbol, ImportAddressSymbol, ImportedFunctionSymbol, DataSymbol, ImportedDataSymbol, ExternalSymbol, LibraryFunctionSymbol, SymbolicFunctionSymbol, LocalLabelSymbol. An unknown name fails the modification.
| Property | Type | Read | Write | Notes |
|---|---|---|---|---|
name |
String | Yes | Yes | Short name (required for create or update) |
full_name |
String | Yes | Yes | Full name including namespace (defaults to name) |
raw_name |
String | Yes | Yes | Raw or mangled name (defaults to full_name) |
binding |
String | Yes | Yes | NoBinding, LocalBinding, GlobalBinding, WeakBinding |
namespace |
String | Yes | Yes | Symbol namespace |
ordinal |
Integer | Yes | Yes | Symbol ordinal (default 0) |
- Multiple symbols of different types can exist at the same address.
- When updating, the existing symbol of the matching type is replaced. The new symbol keeps the binding, namespace and ordinal the edit does not name; its full and raw names follow the new name unless given.
- Only user-defined symbols can be deleted. Loader-generated symbols (e.g.
ImportedFunctionSymbolfrom the file format) cannot be removed and will raise an error.
Section — bv:section/{name}¶
| Property | Type | Read | Write | Notes |
|---|---|---|---|---|
start |
Integer or hex String | Yes | Yes | Start address; reads return a hex string such as 0x401000 |
length |
Integer | Yes | Yes | Size in bytes |
semantics |
String | Yes | Yes | See semantics values below |
type |
String | Yes | Yes | Section type string |
align |
Integer | Yes | Yes | Alignment (default 1) |
entry_size |
Integer | Yes | Yes | Entry size (default 1) |
linked_section |
String | Yes | Yes | Linked section name |
info_section |
String | Yes | Yes | Info section name |
info_data |
Integer | Yes | Yes | Info data value |
auto_defined |
Boolean | Yes | No | Whether the section is loader-defined (read-only) |
Semantics values: DefaultSectionSemantics, ReadOnlyCodeSectionSemantics, ReadOnlyDataSectionSemantics, ReadWriteDataSectionSemantics, ExternalSectionSemantics
- Creating a section requires
startandlength. state: nullcallsremove_user_section. Only user-created sections can be deleted; deleting a loader-defined section fails.- Modifying a user section is implemented as delete-and-recreate with merged properties. Only the properties you specify change; the rest retain their existing values.
- Loader-defined sections (
auto_defined: true, such as.textor.rodata) cannot be modified and will raise an error.
Segment — bv:segment/{address}¶
| Property | Type | Read | Write | Notes |
|---|---|---|---|---|
length |
Integer | Yes | Yes | Total size |
data_offset |
Integer | Yes | Yes | File offset |
data_length |
Integer | Yes | Yes | File size |
readable |
Boolean | Yes | Yes | Read permission |
writable |
Boolean | Yes | Yes | Write permission |
executable |
Boolean | Yes | Yes | Execute permission |
contains_data |
Boolean | Yes | Yes | Contains data flag |
contains_code |
Boolean | Yes | Yes | Contains code flag |
- Creating a segment requires
length,data_offset, anddata_length. state: nullcallsremove_user_segment.- Only user-defined segments can be changed or deleted; an edit to a loader-defined segment fails. Use
bv:region/{name}to overlay part of one. - An update replaces the segment and keeps the extent and flags the edit does not name.
Memory Region — bv:region/{name}¶
Named overlay regions in the binary view's memory map.
| Property | Type | Read | Write | Notes |
|---|---|---|---|---|
start |
Integer or hex String | Yes | Create only | Start address; required to create, immutable afterwards |
length |
Integer or hex String | Yes | Create only | Size in bytes; required to create, immutable afterwards |
source |
Object | No | Create only | Backing bytes: {"raw_offset": N} copies bytes from the Raw file, {"bytes": "90c3"} supplies exact-length hex bytes; omit for an unbacked fill |
flags |
Integer or hex String | Yes | Yes | Binary Ninja SegmentFlag bitmask (0 to 2^32-1) |
enabled |
Boolean | Yes | Yes | Whether the region is active |
rebaseable |
Boolean | Yes | Yes | Whether the region is rebaseable |
fill |
Integer or hex String | Yes | Yes | Fill byte (0–255) |
display_name |
String | Yes | Yes | Display name |
end, has_target, absolute_address_mode, local |
— | Yes | No | Read-only |
- Creating a region requires
startandlength. - Extent and backing cannot change. To change them, add a region with a new, unique name.
state: nullremoves the region.- Region deletion is reverted with Binary Ninja Undo, not the Sidekick Transaction Log revert. Property edits and creation can be reverted from the log;
enabled: falseis the revertible alternative to deletion.
{"uri": "bv:region/patch1", "state": {"start": "0x1000", "length": 4, "source": {"bytes": "90909090"}}}
Tag — bv:tag/{address}/{type_name}¶
| Property | Type | Read | Write | Notes |
|---|---|---|---|---|
data |
String | Yes | Yes | Tag content |
icon |
String | No | Yes | Icon; accepted only when the tag type does not exist yet and is being auto-created. Supplying icon for an existing tag type fails with an unknown-attributes error (use bv:tagtype/{name} to change a type icon) |
- If the tag type does not exist, it is created automatically.
- When
datais given, an existing tag of the same type at the address is replaced. Whendatais omitted, an existing tag is left as it is.
Tag Type — bv:tagtype/{name}¶
| Property | Type | Read | Write | Notes |
|---|---|---|---|---|
icon |
String | Yes | Yes | Icon character |
state: nullcallsremove_tag_type. It fails while tags of that type exist; delete those tags first.- Changing the icon updates the tag type in place, so its tags are kept. Omitting
iconleaves an existing tag type unchanged.
External Library — bv:library/{name}¶
| Property | Type | Read | Write | Notes |
|---|---|---|---|---|
backing_file |
String | Yes | Yes | Name or on-disk path of an existing file in the same Binary Ninja project. Setting it on a view that is not in a project, or naming a file that is not in the project, fails |
state: nullcallsremove_external_library. It fails while an external location refers to the library; delete those locations first.
External Location — bv:external/{library}/{source_address}¶
source_address is the address of the import reference in the binary (the source symbol address), which uniquely identifies the location even when multiple symbols share a name.
| Property | Type | Read | Write | Notes |
|---|---|---|---|---|
source_symbol |
String | Yes | No | Name of the source symbol (read-only) |
target_symbol |
String | Yes | Yes | Symbol name in the target library |
target_address |
Integer or hex String | Yes | Yes | Address in the target library; reads return a hex string (null if none) |
- The external library must exist before creating an external location.
Imported Function — bv:import/{address}¶
Apply a recovered signature to an imported symbol and have it propagate to every caller automatically. This is the right URI for the import-type-recovery workflow — it hides the platform-specific plumbing behind a single address and a function type.
address is the IAT slot (PE) or GOT entry (ELF) — the address Binary Ninja flags with ImportAddressSymbol, same value the enumerator returns as iat_or_got.
| Property | Type | Read | Write | Notes |
|---|---|---|---|---|
symbol |
String | Yes | No | Short name of the imported symbol (read-only) |
type |
String | Yes | Yes | Function type — e.g. "int32_t(const char* fmt, ...)", not pointer-to-function. Reads null while the import has no stub and its pointer variable is not a function pointer |
confidence |
Integer | Yes | Yes | 0–255. Attached to the IAT data variable's pointer type when the signature is written to the IAT slot (PE). Advisory when the type is set on an ELF PLT stub, where Binary Ninja drops per-function-type confidence (see Function notes) |
library |
String | Yes | No | Attributed library when the format states one (PE); null on ELF |
plt_address |
String | Yes | Yes | ELF PLT stub address. Read-side: the resolved stub. Write-side: optional hint that short-circuits code-ref lookup |
- ELF: the handler locates the PLT stub that jumps through the GOT entry (the referencing function Binary Ninja itself marked as an import stub) and calls
Function.set_user_typeon it. A function that merely calls through the entry is never treated as the stub. Analysis propagates the stub's signature to every caller's HLIL automatically. If you already know the PLT stub's address, passplt_addressin the state to skip the lookup. - PE: callers call through the IAT slot — the handler wraps the function type in a pointer and assigns it to the IAT data variable. If Binary Ninja recognized a jump thunk for the slot, the thunk is typed instead, as on ELF. Callers see the type through the normal indirect-call pointer propagation path.
- The
typeattribute must be a function type. Pointer-to-function forms are rejected with a clear error — pointer wrapping on PE is handled internally so callers use one form on both platforms. state: nulltakes back a type you applied to the import's own pointer variable, leaving the variable analysis defined;{"type": null}does the same. Neither strips a type you did not author. A stub keeps its type, because Binary Ninja cannot clear a function's user type:state: nulldoes nothing there and{"type": null}is rejected.- Reverting a type applied over an analysis-defined pointer variable removes your type rather than writing the old one back. Elsewhere it restores the previous type at the place the edit wrote it (the stub, or the function a
plt_addresshint named). One case cannot be reverted: typing an import whose pointer variable you had defined yourself as something other than a function pointer. - Why not
bv:datavar/{got_addr}? On ELF, typing the GOT data variable does not propagate to callers. The GOT slot is not what analysis consults when resolving calls through the PLT — the stub's own function signature is.bv:importtargets the stub, which is the only thing post-load analysis honors.
{
"uri": "bv:import/0x5cac0",
"state": {"type": "int32_t(const char* ident, int32_t option, int32_t facility)"}
}
{
"uri": "bv:import/0x5cac0",
"state": {
"type": "int32_t(const char* ident, int32_t option, int32_t facility)",
"plt_address": "0xc060"
}
}
Component — bv:component/{component_id}¶
component_id can be a GUID or a component name. The lookup searches recursively through all nested components. A new component is named by its URI, so a name given while creating one must match it.
| Property | Type | Read | Write | Notes |
|---|---|---|---|---|
name |
String | Yes | Yes | Component display name |
functions |
Array[String] | Yes | Yes | Function addresses (hex strings); setting this replaces the entire list |
datavars |
Array[String] | Yes | Yes | Data variable addresses (hex strings); setting this replaces the entire list |
state: nullcallsremove_component.- Use
$add/$removecollection operators to add or remove individual entries without replacing the full list.
Stack Variable — bv:stack/{function_address}/variable/{offset}¶
offset formats: -0x10, 0x10, -16, 16
| Property | Type | Read | Write | Notes |
|---|---|---|---|---|
name |
String | Yes | Yes | Variable name; defaults to var_<hex offset> if omitted |
type |
String | Yes | Yes | Variable type; defaults to int if omitted |
offset |
Integer | Yes | No | Stack offset (from URI; read-only in state) |
state: nullcallsdelete_user_stack_var(offset), which returns the variable to what analysis computes. This cannot be reverted.- Reverting a rename or retype of a variable analysis had defined removes your definition rather than writing the old values back.
- Creating or updating uses
create_user_stack_var(offset, type, name). The variable is recreated on every write and keeps the name or type the edit does not give.
Stack Call Adjustment — bv:stack/{function_address}/call_adjustment/{instruction_address}¶
| Property | Type | Read | Write | Notes |
|---|---|---|---|---|
value |
Integer | Yes | Yes | Stack adjustment override at this call site; reads null when there is none |
state: null(orvalue: null) removes the override, so analysis derives the adjustment from the call type.
Stack Return Adjustment — bv:stack/{function_address}/return_adjustment¶
| Property | Type | Read | Write | Notes |
|---|---|---|---|---|
value |
Integer | Yes | Yes | Return stack adjustment for the function |
state: nullresets the adjustment toOffsetWithConfidence(0). This cannot be reverted.
Result Structure¶
These structures describe the processor's internal result. Through update_database you see a success message with the transaction ID and an effects report. If any modification fails, the whole transaction fails with Failed to apply N modification(s): <uri>: <error> and nothing is committed for the failing binary view. Modifications after the first failure are reported as skipped with the reason batch aborted due to earlier failure; a modification skipped because of a failed dependency has the reason dependency failed: <ids>.
BatchResult¶
| Field | Type | Description |
|---|---|---|
results |
Array[ModificationResult] | Individual result for each modification |
succeeded_ids |
Array[String] | IDs of modifications that succeeded |
failed_ids |
Array[String] | IDs of modifications that failed |
skipped_ids |
Array[String] | IDs of skipped modifications, either because a dependency failed (dependency failed: <ids>) or because an earlier failure aborted the batch (batch aborted due to earlier failure) |
undo_id |
String | Binary Ninja undo action ID |
committed |
Boolean | true if changes were committed; false if rolled back |
all_succeeded |
Boolean | true if there were no failures |
ModificationResult¶
| Field | Type | Description |
|---|---|---|
uri |
String | The modification's target URI |
id |
String | null | The modification ID, if one was provided |
status |
"success" | "failed" | "skipped" |
Outcome |
error |
String | null | Error message when status is "failed" |
reason |
String | null | Skip reason when status is "skipped" |
Error Reference¶
| Error type | When it occurs |
|---|---|
ExpectationError |
expect precondition check failed |
ValueError |
Duplicate modification id; circular dependency; unknown dependency id; Invalid target format: <uri> (the object type is known but the path matches none of its patterns); missing required properties; invalid register name in clobbered_regs; attempt to delete a non-user-defined object |
ValueError (unknown property) |
Unknown attributes for <uri>: <names>: the state contains a property the handler does not accept (misspelled, or read-only such as offset on a stack variable). The whole batch fails |
NotImplementedError |
No handler registered for <uri>: the object type (e.g. bv:foo) is unknown |
Examples¶
Rename a function and its variables¶
{
"description": "Recover session handling function",
"binary_view_changes": [{
"modifications": [
{"uri": "bv:function/0x406ec0", "state": {"name": "command_interpreter"}},
{"uri": "bv:function/0x406ec0/variable/arg1", "state": {"name": "db", "type": "int64_t*"}},
{"uri": "bv:function/0x406ec0/variable/arg2", "state": {"name": "input", "type": "FILE*"}},
{"uri": "bv:function/0x406ec0/variable/var_28", "state": {"name": "current_user"}},
{"uri": "bv:function/0x406ec0/variable/var_30_1", "state": {"name": "input_buffer"}}
]
}]
}
Define a struct and apply it to a variable¶
{
"description": "Define connection struct",
"binary_view_changes": [{
"modifications": [
{
"id": "def_conn",
"uri": "bv:type/Connection",
"state": {"definition": "struct Connection { int fd; char* hostname; uint16_t port; }"}
},
{
"uri": "bv:function/0x401000/variable/arg1",
"state": {"type": "struct Connection*"},
"depends_on": ["def_conn"]
}
]
}]
}
Annotate a crypto loop¶
{
"description": "Mark AES key schedule",
"binary_view_changes": [{
"modifications": [
{"uri": "bv:function/0x401200", "state": {"comment": "AES key schedule loop"}},
{"uri": "bv:function/0x401200/instruction/0x401210", "state": {"highlight": "yellow", "comment": "Round key XOR"}},
{"uri": "bv:function/0x401200/instruction/0x401230", "state": {"highlight": "yellow", "comment": "S-box substitution"}}
]
}]
}
Guard a rename with a precondition¶
{
"description": "Rename only if still auto-named",
"binary_view_changes": [{
"modifications": [
{
"uri": "bv:function/0x401000",
"expect": {"name": "sub_401000"},
"state": {"name": "init_config"}
}
]
}]
}