binaryninja

tool binary ninja HLIL · MLIL
UI tipsIL levelsPython API FunctionsXrefsPatch HeadlessCTF patterns
01UI Tips & Shortcuts
Navigation
ActionShortcut
Go to addressG or Ctrl+G
Navigate backAlt+← / Backspace
Navigate forwardAlt+→
Jump to functionCtrl+Shift+F
Search stringsCtrl+Shift+S
Rename symbolN
Change typeY
Cross-referencesX
Switch IL levelCtrl+1/2/3/4/5/6
Toggle graph/linearSpace
Comment;
Python consoleCtrl+\
Views
# View → Linear Disassembly (classic view)
# View → Graph (CFG of function)
# View → High Level IL (HLIL — C-like)
# View → Medium Level IL (MLIL — SSA)
# View → Low Level IL (LLIL — near assembly)
# View → Lifted IL (raw lift)

# Sidebar panels:
# Symbols — all named functions/vars
# Cross References — xrefs panel
# Types — struct/type editor
# Strings — all found strings
# Tags — bookmarks

# Python console: Ctrl+\  (most powerful)
# Access current binary via: bv (BinaryView)
# Access current function:   current_function
# Access current address:    here
02IL Levels
IL hierarchy
LevelNameDescriptionBest for
DisassemblyNative asmRaw architecture instructionsExact byte analysis, patches
LLILLow Level ILArch-independent, near-asm semanticsEmulation, precise analysis
MLILMedium Level ILStack-to-variable, SSA form, typedData flow analysis, slicing
HLILHigh Level ILC-like, control flow lifted, readableFast manual RE, finding logic
HLIL SSAHLIL + SSASingle static assignment of HLILScripted analysis, taint
# In Python console: access each level from a function
func.llil          # LowLevelILFunction
func.mlil          # MediumLevelILFunction
func.hlil          # HighLevelILFunction
func.hlil.ssa_form # HLIL SSA
03Python API Basics
Console (interactive)
# In Binja Python console (Ctrl+\):
bv                          # current BinaryView
here                        # current address (int)
current_function            # Function at cursor
current_basic_block         # BasicBlock at cursor

# BinaryView basics
bv.file.filename            # file path
bv.arch                     # architecture
bv.start                    # start address
bv.entry_point              # entry point
list(bv.functions)          # all functions
list(bv.symbols.values())   # all symbols
bv.get_symbol_by_raw_name('main')
bv.get_function_at(0x401234)
Script file API
import binaryninja as bn

# Open binary
bv = bn.open_view('./challenge')
bv.update_analysis_and_wait()  # ensure fully analyzed

# Find function by name
func = bv.get_functions_by_name('main')[0]

# Find function at address
func = bv.get_function_at(0x401234)

# Iterate all functions
for func in bv.functions:
    print(func.name, hex(func.start))

# Close properly
bv.file.close()

# Headless mode (no GUI)
with bn.open_view('./challenge') as bv:
    bv.update_analysis_and_wait()
    # ... analyze ...
04Functions & Variables
Function inspection
func = bv.get_function_at(0x401234)

# Basic info
func.name                   # 'check_password'
func.start                  # 0x401234
func.parameter_vars         # list of params
func.vars                   # all local vars
func.stack_layout           # stack frame layout
func.basic_blocks           # list of BasicBlock
func.callees                # functions this calls
func.callers                # functions that call this

# Rename
func.name = 'win_function'

# Iterate HLIL instructions
for block in func.hlil:
    for instr in block:
        print(instr.operation, instr)

# Find specific HLIL operations
from binaryninja.highlevelil import HighLevelILOperation
for instr in func.hlil.instructions:
    if instr.operation == HighLevelILOperation.HLIL_CALL:
        print('call at', hex(instr.address), instr)
Variables & types
# Variables
for var in func.vars:
    print(var.name, var.type)

# Rename variable
var = func.vars[0]
func.create_user_var(var.storage, var.type, 'new_name')

# Change type
from binaryninja import Type
func.create_user_var(var.storage, Type.int(4), 'my_int')

# Define struct type
s = bn.Structure()
s.append(bn.Type.int(4), 'field1')
s.append(bn.Type.pointer(bv.arch, bn.Type.char()), 'name')
bv.define_user_type('MyStruct', bn.Type.structure_type(s))

# Apply type to variable
t = bv.get_type_by_name('MyStruct')
func.create_user_var(var.storage, bn.Type.pointer(bv.arch, t), 'obj')
05Search & Xrefs
Search
# Find string in binary data
for s in bv.strings:
    if 'flag' in s.value.lower():
        print(hex(s.start), s.value)

# Find bytes pattern
results = bv.find_all_data(bv.start, bv.end,
    bn.DataBuffer(bytes.fromhex('5fc3')))  # pop rdi; ret
for addr, _, _ in results:
    print(hex(addr))

# Find disassembly text
results = bv.find_all_text(bv.start, bv.end, 'strcmp')
for addr, _, _ in results:
    print(hex(addr))

# Find HLIL expression
results = bv.find_all_constant(bv.start, bv.end, 0x1337)
for addr, _, _ in results:
    print(hex(addr))
Cross-references
# All code references TO an address
for xref in bv.get_code_refs(0x401234):
    print(hex(xref.address), xref.function.name)

# All data references TO an address
for xref in bv.get_data_refs(0x404060):
    print(hex(xref))

# Code refs FROM an address
for xref in bv.get_code_refs_from(0x401234):
    print(hex(xref))

# Callees of a function (who does it call?)
for callee in func.callees:
    print(callee.name)

# Callers of a function (who calls it?)
for caller in bv.get_callers(func.start):
    print(hex(caller))
06Patching
Patch bytes & assembly
# Write raw bytes
bv.write(0x401234, b'\x90\x90')         # NOP NOP
bv.write(0x401234, bytes.fromhex('9090'))

# Always patch (even read-only sections)
bv.write(0x401234, b'\xeb\x0a')          # JMP +10

# Assemble and write
from binaryninja import Architecture
arch = bv.arch
asm, _ = arch.assemble('nop; nop')
bv.write(0x401234, asm)

# Save patched binary
bv.save_auto_snapshot()
bv.file.save_with_options('./patched', None)

# Export patched binary
with open('./patched', 'wb') as f:
    f.write(bytes(bv[bv.start:bv.end]))
Read memory
# Read raw bytes
data = bv.read(0x401234, 16)     # 16 bytes
print(data.hex())

# Read integer
val = bv.read_int(0x404060, 8, False)  # 8 bytes, unsigned

# Check segment permissions
seg = bv.get_segment_at(0x401234)
seg.readable
seg.writable
seg.executable

# List all segments
for seg in bv.segments:
    print(hex(seg.start), hex(seg.end),
          'r' if seg.readable else '-',
          'w' if seg.writable else '-',
          'x' if seg.executable else '-')
07CTF Patterns
XOR decode loop detection & extraction
import binaryninja as bn
from binaryninja.highlevelil import HighLevelILOperation as Op

with bn.open_view('./challenge') as bv:
    bv.update_analysis_and_wait()
    for func in bv.functions:
        # Look for functions with XOR operations
        xor_count = sum(1 for i in func.hlil.instructions
                        if i.operation == Op.HLIL_XOR)
        if xor_count > 3:
            print(f'XOR-heavy function: {func.name} @ {hex(func.start)}')
            # Try to extract constants near XOR
            for instr in func.hlil.instructions:
                if instr.operation == Op.HLIL_XOR:
                    print(' XOR:', instr)
QUICK REFERENCE →  bv current BinaryView (console)  · here current address  · current_function function at cursor  · func.hlil high-level IL  · bv.strings all strings  · bv.get_code_refs(addr) xrefs  · bv.write(addr, bytes) patch  · bn.open_view('./bin') headless  · Ctrl+\ Python console, N rename, X xrefs, Space graph