This is a work in progress by someone who is learning about Binary Ninja.
References
- https://api.binary.ninja/binaryninja.binaryview-module.html
- https://gist.github.com/psifertex/6fbc7532f536775194edd26290892ef7
Get database name
bv.file.database.file
Get original file name
bv.file.original_filename
APIs for accessing snapshots
[x for x in dir(bv.file.database) if "snapshot" in x]
['current_snapshot', 'get_snapshot', 'remove_snapshot', 'snapshots', 'trim_snapshot']
Get Architecture
bv.arch
<arch: x86_64>
Get entry point
"0x%x" %bv.entry_point
'0x140002130'
Get endianness
bv.endianness
<Endianness.LittleEndian: 0>
Get a list of segments
bv.segments
Get a list of segments and print them
for seg in bv.segments:print(seg)
<segment: 0x140000000-0x140000400, r-->
<segment: 0x140001000-0x140008d6e, r-x>
<segment: 0x140009000-0x140009c66, r-->
<segment: 0x14000a000-0x14000a450, rw->
<segment: 0x14000b000-0x14000b33c, r-->
Segment attributes
[x for x in dir(seg) if "__" not in x]
['auto_defined', 'data_end', 'data_length', 'data_offset', 'end', 'executable', 'handle', 'readable', 'relocation_count', 'relocation_ranges', 'relocation_ranges_at', 'start', 'writable']
Get segment at address
bv.get_segment_at(here)
<segment: 0x140001000-0x140008d6e, r-x>
APIs for working with segments
[x for x in dir(bv) if "segment" in x]
['add_auto_segment', 'add_user_segment', 'get_segment_at', 'remove_auto_segment', 'remove_user_segment', 'segments']
Get all sections
bv.sections
Get section at address
bv.get_sections_at(here) # here is the address of cursor
[<section .text: 0x140001000-0x140008d6e>]
APIs for working with sections
[x for x in dir(bv) if "_section" in x]
['add_auto_section', 'add_user_section', 'get_section_by_name', 'get_sections_at', 'get_unique_section_names', 'remove_auto_section', 'remove_user_section']
First a lesson in how Binary Ninja organizes functions, basic blocks and instructions.
- All Function objects are contained within a BinaryView object.
- All BasicBlock objects are contained within a Function.
- All instruction objects are contained within BasicBlock objects. "
Get all functions
bv.functions
Loop through all functions
for func in bv.functions:
print(func)
Function type
type(func)
<class 'binaryninja.function.Function'>
Get function start address by address
bv.get_functions_containing(here) # returns list
[<func: x86_64@0x140008260>]
Get function name by start address
bv.get_function_at(0x140008260)
<func: x86_64@0x140008260>
Get function address by name
bv.get_functions_by_name("start_address")
[<func: x86_64@0x1400029b0>] # returns list
Get function arguments
>>> ff = bv.get_function_at(0x140008260)
>>> ff.function_type.parameters
[uint64_t* arg1]
Get basic blocks in a function
>>> for bb in ff.basic_blocks:print(bb)
<block: x86_64@0x140008260-0x140008284>
>>>
>>> ff = bv.get_function_at(here)
>>> for bb in ff.basic_blocks:print(bb)
<block: x86_64@0x140001740-0x140001767>
<block: x86_64@0x14000176f-0x140001775>
<block: x86_64@0x140001787-0x14000178c>
<block: x86_64@0x140001775-0x140001787>
<block: x86_64@0x140001767-0x14000176f>
Get basic block at address
bv.get_basic_blocks_at(0x140001770)
[<block: x86_64@0x14000176f-0x140001775>] # returns list
Get next basic block start address after address
bv.get_next_basic_block_start_after(here)
Get the end address of the previous basic block from an address
bv.get_previous_basic_block_end_before(here)
Get the start address of the previous basic block from an address
bv.get_previous_basic_block_start_before(here)
Get disassembly instruction at address
>>> bv.get_disassembly(here) # here is the address of cursor
'xor edx, edx'
Loop through all instructions in function
ff = bv.get_function_at(0x140008260)
>>> for instru in ff.instructions:print(instru)
(['mov', ' ', 'qword ', '[', 'rsp', '+', '0x8', ']', ', ', 'rcx'], 5368742496)
(['sub', ' ', 'rsp', ', ', '0x28'], 5368742501)
(['call', ' ', 'qword ', '[', 'rel ', '0x1400090d0', ']'], 5368742505)
(['mov', ' ', 'r8', ', ', 'qword ', '[', 'rsp', '+', '0x30', ']'], 5368742511)
(['xor', ' ', 'edx', ', ', 'edx'], 5368742516)
(['mov', ' ', 'rcx', ', ', 'rax'], 5368742518)
(['call', ' ', 'qword ', '[', 'rel ', '0x1400090c0', ']'], 5368742521)
(['add', ' ', 'rsp', ', ', '0x28'], 5368742527)
(['retn', ' '], 5368742531)
Loop through Medium Level IL (MLIL) instructions in function
for i in ff.mlil_instructions:
... print("0x%x %s" % (i.address, i))
...
...
0x140008260 arg_8 = arg1
0x140008269 rax = GetProcessHeap()
0x14000826f r8 = arg_8
0x140008276 rcx = rax
0x140008279 rax_1 = HeapAlloc(rcx, HEAP_NONE, r8)
0x140008283 return rax_1
Get Operand
instru[0][0]
'retn'
Attributes for working with operands
[x for x in dir(instru[0][0]) if "__" not in x]
['_from_core_struct', '_get_core_struct', 'address', 'confidence', 'context', 'operand', 'size', 'text', 'type', 'typeNames', 'value', 'width']
Get all symbols
bv.get_symbols()
Get symbol by name
bv.symbols["GetCommandLineW"]
[<ImportAddressSymbol: "GetCommandLineW" @ 0x140009000>] # returns list
APIs for working with symbols
[x for x in dir(bv) if "symbol" in x]
['bulk_modify_symbols', 'define_auto_symbol', 'define_auto_symbol_and_var_or_function', 'define_user_symbol', 'get_symbol_at', 'get_symbol_by_raw_name', 'get_symbols', 'get_symbols_by_name', 'get_symbols_by_raw_name', 'get_symbols_of_type', 'has_symbols', 'symbols', 'undefine_auto_symbol', 'undefine_user_symbol']
Get offsets to string references
bv.strings
[<AsciiString: 0x14000004d, len 0x2c>, <AsciiString: 0x1400000b8,.... removed...
Get ASCII string at address
ss = bv.get_ascii_string_at(here)
ss.value
'blah.exe"
Binary ninja has multiple cross-reference (aka xrefs) types
Type | Description |
---|---|
Code References | References to and from code |
Data References | References created by data |
Variable References | Variable References are all the set of uses of a given variable. |
Type References | Type-to-Type-References |
APIs for working with cross-references
>>> [x for x in dir(bv) if "refs" in x]
['get_code_refs', 'get_code_refs_for_type', 'get_code_refs_for_type_field', 'get_code_refs_for_type_fields_from', 'get_code_refs_for_type_from', 'get_code_refs_from', 'get_data_refs', 'get_data_refs_for_type', 'get_data_refs_for_type_field', 'get_data_refs_from', 'get_type_refs_for_type', 'get_type_refs_for_type_field']
Get code references from an address
>>> for ea in bv.get_code_refs(here):print("0x%x, %s, %s" % (ea.address, ea.arch, ea.function))
0x14000241e, x86_64, int64_t sub_1400023f0(char* arg1, void* arg2, char* arg3, void* arg4, char* arg5)
0x140002473, x86_64, int64_t sub_1400023f0(char* arg1, void* arg2, char* arg3, void* arg4, char* arg5)
0x1400024f5, x86_64, int64_t sub_1400023f0(char* arg1, void* arg2, char* arg3, void* arg4, char* arg5)
>>> type(ea)
<class 'binaryninja.binaryview.ReferenceSource'>
>>> type(ea.function)
<class 'binaryninja.function.Function'>
API referencing data cross-references
'get_data_refs', 'get_data_refs_from',
Unknown
API referencing type cross-references
'get_code_refs_for_type', 'get_code_refs_for_type_field', 'get_code_refs_for_type_fields_from', 'get_code_refs_for_type_from', 'get_data_refs_for_type', 'get_data_refs_for_type_field', 'get_type_refs_for_type', 'get_type_refs_for_type_field'
There are a lot of variations with creating types. The following link is the most useful description of Types usage.
There are two approaches that can be used by Binary Ninja for searching. The first approach uses Binary Ninja APIs.
Find all offsets of a constant by value.
bv.find_all_constant(bv.start, bv.end, constant) # example constant 0x90
Find all offset of a data.
bv.find_all_data(bv.start, bv.end, byte_pattern) # example byte_pattern b"\x90\x90\x90\x90"
Find all offsets to a string
bv.find_all_text(bv.start, bv.end, find_string) # example find_string "FindClose"
Find next address of constant by value
bv.find_next_constant(bv.start, constant)# example constant 0x90
Find next address of data by byte
bv.find_next_data(bv.start, byte_pattern) # example byte_pattern b"\x90\x90\x90\x90"
Find next address of text by string
bv.find_next_text(bv.start, find_string) # example find_string "FindClose"
The second approach treats each segment, iterates through them and searches the data.
find_me = b"\xe8\x16\x12\x00\x00"
reader = BinaryReader(bv)
for segment in bv.segments:
offset = 0
reader.seek(segment.start)
data = reader.read(segment.data_length)
offset = data.find(find_me)
if offset != -1:
print("found at 0x%x" % (offset + segment.start))
Note: Comments inserted through the GUI to functions are not accessible through the binary view (bv) APIs. For example, a comment of 'test one two three' was inserted via the GUI (;
) but the comment is not accessible through the bv
api. Binary Ninja functions that start with `current_* are not available through headless mode.
>>> current_function.get_comment_at(here)
'test one two three'
>>> bv.get_comment_at(here)
''
Add comment to address
bv.set_comment_at(here, "hi")
Get Comment
bv.get_comment_at(here)
Get all API (non-function) Comments
>>> bv.address_comments
{5368718021: 'hi', 5368718150: 'test', 5368718335: 'hi'}
Note: Function comments are not the same as function comments in IDA. Function comments in Binary Ninja appear to be related to the usage of adding comments in a function using the GUI.
Get function comment address
current_function.get_comment_at(here)
Set function comment at address
current_function.set_comment_at(here)
Get highlighted data in the GUI
get_selected_data()
b'\xff\x15\xdcm\x00\x00H\xc7D$ \x00\x00\x00\x00E3\xc9\x8bL$<D\x8b\xc1'
Write persistent data to the database
bv.store_metadata(key, value)
Get persistent data from the database
bv.get_metadata(key, value)
The first argument is a key that can be of type int, bool, str, bytes, float and list. The second argument is the value to be save or retrieved from the database.
Highlight a selected address
ff = bv.get_functions_containing(here) # the first argument is an address
ff[0].set_auto_instr_highlight(here, highlight.HighlightColor(red=12, green=0, blue=0))
Details on color mixing
>>> help(highlight.HighlightColor)
Help on class HighlightColor in module binaryninja.highlight:
class HighlightColor(builtins.object)
| HighlightColor(color=None, mix_color=None, mix=None, red=None, green=None, blue=None, alpha=255)
Read and write bytes
data = bv.read(address, length) # read data
bv.write(address, data) # patch address
Simple script for printing all instructions.
import sys
try:
import binaryninja
except ModuleNotFoundError:
exit()
with binaryninja.open_view(sys.argv[1]) as bv:
for func in bv.functions:
for instru in func.instructions:
print("0x%x: %s" % (instru[1], bv.get_disassembly(instru[1])))
from collections import Counter
XOR_FUNC_THRESHOLD = 8
def get_xor_instru(instru):
if not instru:
return False
ins_type = instru[0][0]
# skip XOR instructions
if ins_type.text != "xor":
return False
src = instru[0][2]
dst = instru[0][4]
if src == dst:
return False
return True
def loop_through_all(bv, *options):
"""
:param bv:
:param options:
:return: list []
"""
output = ""
# loop through all functions
for func in bv.functions:
temp_func_xor_instru = []
temp_func_addr_xor = []
# loop through all instruction
for ins in func.instructions:
# options is a list that can be passed a mnemonic
if "xor" in options:
# check if xor is the mnemonic
tt = get_xor_instru(ins)
# if so,
if tt:
# used as a counter object to count unique xor instructions
temp_func_xor_instru.append(bv.get_disassembly(ins[1]))
# used to store XOR instruction and address
temp_func_addr_xor.append((ins[1], bv.get_disassembly(ins[1])))
if not temp_func_xor_instru:
continue
# calculate uniqueness of xor for function
count_dracula = Counter(temp_func_xor_instru)
# get count of XOR instructions
count = sum([x for x in count_dracula.values()])
# assume manual analysis is needed, code is likely a packer or encryption
if count > XOR_FUNC_THRESHOLD:
output += "XOR Function:\n"
output += "Complex XOR threshold of 0x%x found in function 0x%x\n" % (count, func.start)
for vk in count_dracula.keys():
output += "%s appeared 0x%x times\n" % (vk, count_dracula[vk])
continue
# get individual instructions
for entry in temp_func_addr_xor:
output += "XOR Instruction: 0x%x %s\n" % (entry[0], entry[1])
return output
def dev():
print(loop_through_all(bv,"xor"))
dev()
import logging
logging.basicConfig()
logging.getLogger().setLevel(logging.DEBUG)
file_name = ""
try:
import binaryninja
logging.debug("BinaryNinja has been imported")
except ModuleNotFoundError:
logging.critical("BinaryNinja module is not installed.")
exit()
with binaryninja.open_view(file_name) as bv:
print("bv.address_comments, %s" % (bv.address_comments))
print("bv.address_size, %s" % (bv.address_size))
print("bv.allocated_ranges, %s" % (bv.allocated_ranges))
print("bv.analysis_changed, %s" % (bv.analysis_changed))
print("bv.analysis_info, %s" % (bv.analysis_changed))
print("bv.analysis_progress, %s" % (bv.analysis_progress))
print("bv.arch %s " % (bv.arch))
print("bv.available_view_types %s" % (bv.available_view_types))
print("bv.basic_blocks, type: Generator")
for cc, gg in enumerate(bv.basic_blocks):
print("\tbasic block:", gg)
print ("\tbasic block instances:", [tt for tt in dir(gg) if "__" not in tt])
if cc == 3:
break
print("bv.data_tags, %s" % (bv.data_tags))
print("bv.data_vars, %s" % (bv.data_vars))
print("bv.end, %s" % (bv.end))
print("bv.endianness, %s" % (bv.endianness))
print("bv.entry_function, %s" % (bv.entry_function))
print("bv.entry_point, %s" % (bv.entry_point))
print("bv.executable, %s" % (bv.executable))
print("bv.functions, %s" % (bv.functions))
for cc, gg in enumerate(bv.functions):
print("\tfunctions:", gg)
print ("\tfunctions instance:", [tt for tt in dir(gg) if "__" not in tt])
if cc == 3:
break
print("bv.global_pointer_value, %s" % (bv.global_pointer_value))
print("bv.has_data_variables, %s" % (bv.has_data_variables))
print("bv.has_database, %s" % (bv.has_database))
print("bv.has_functions, %s" % (bv.has_functions))
print("bv.has_symbols, %s" % (bv.has_symbols))
print("bv.hlil_basic_blocks, %s" % (bv.hlil_basic_blocks))
print("v.hlil_basic_blocks, %s" % (bv.hlil_basic_blocks))
print("bv.hlil_instructions, %s" % (bv.hlil_instructions))
print("bv.instructions, %s" % (bv.instructions))
print("bv.linear_disassembly, %s" % (bv.linear_disassembly))
for cc, gg in enumerate(bv.linear_disassembly):
print("\tlinear_disassembly:", gg)
print ("\tlinear_disassembly instance:", [tt for tt in dir(gg) if "__" not in tt])
if cc == 3:
break
print("bv.llil_basic_blocks, %s" % (bv.llil_basic_blocks))
for cc, gg in enumerate(bv.llil_basic_blocks):
print("\tllil_basic_blocks:", gg)
print ("\tllil_basic_blocks instance:", [tt for tt in dir(gg) if "__" not in tt])
if cc == 3:
break
print("bv.llil_instructions, %s" % (bv.llil_basic_blocks))
for cc, gg in enumerate(bv.llil_basic_blocks):
print("\tllil_basic_blocks:", gg)
print ("\tllil_basic_blocks instance:", [tt for tt in dir(gg) if "__" not in tt])
if cc == 3:
break
print("bv.long_name, %s" % (bv.long_name))
print("bv.llil_instructions, %s" % (bv.llil_instructions))
for cc, gg in enumerate(bv.llil_instructions):
print("\tllil_instructions:", gg)
print ("\tllil_instructions instance:", [tt for tt in dir(gg) if "__" not in tt])
if cc == 3:
break
print("bv.long_name, %s" % (bv.long_name))
print("bv.max_function_size_for_analysis, %s" % (bv.max_function_size_for_analysis))
print("bv.mlil_basic_blocks, %s" % (bv.mlil_basic_blocks))
for cc, gg in enumerate(bv.mlil_basic_blocks):
print("\tmlil_basic_blocks:", gg)
print ("\tmlil_basic_blocks instance:", [tt for tt in dir(gg) if "__" not in tt])
if cc == 3:
break
print("bv.mlil_instructions, %s" % (bv.mlil_instructions))
for cc, gg in enumerate(bv.llil_basic_blocks):
print("\tmlil_instructions:", gg)
print ("\tmlil_instructions instance:", [tt for tt in dir(gg) if "__" not in tt])
if cc == 3:
break
print("bv.modified), %s" % (bv.modified))
print("bv.name, %s" % (bv.name))
print("bv.namespaces, %s" % (bv.namespaces))
print("bv.new_auto_function_analysis_suppressed, %s" % (bv.new_auto_function_analysis_suppressed))
print("bv.offset, %s" % (bv.offset))
print("bv.parameters_for_analysis, %s" % (bv.parameters_for_analysis))
print("bv.parent_view, %s" % (bv.parent_view))
print("bv.platform, %s" % (bv.platform))
print("bv.registered_view_type, %s" % (bv.registered_view_type))
print("bv.relocatable, %s" % (bv.relocatable))
print("bv.relocation_ranges, %s" % (bv.relocation_ranges))
print("bv.saved, %s" % (bv.saved))
print("bv.sections, %s" % (bv.sections))
print("v.segments), %s" % (bv.segments))
print("bv.session_data, %s" % (bv.session_data))
print("bv.start, 0x%x" % (bv.start))
print("bv.strings, %s" % (bv.strings))
print("bv.symbols, %s" % (bv.symbols))
print("bv.tag_types, %s" % (bv.tag_types))
print("bv.type_libraries, %s" % (bv.type_libraries))
print("bv.type_names, %s" % (bv.type_names))
print("bv.types, %s" % (bv.types))
print("bv.view_type, %s" % (bv.view_type))
from binaryninja import LowLevelILInstruction
def explore_LowLevelILInstruction(bv, func=None):
ll = set([])
for func in bv.functions:
for block in func.low_level_il.basic_blocks:
for instr in block:
if isinstance(instr, LowLevelILInstruction):
tt = instr.operation
if tt not in ll:
ll.add(tt)
print(binaryninja.LowLevelILOperation(tt).name)
print("\t0x%x %s" % (instr.address, instr))
print("\t%s" % (bv.get_disassembly(instr.address)))
for oper in instr.operands:
if isinstance(oper, LowLevelILInstruction):
tt = oper.operation
if tt not in ll:
ll.add(tt)
print(binaryninja.LowLevelILOperation(tt).name)
print("\t0x%x %s" % (instr.address, instr))
print("\t%s" % (bv.get_disassembly(instr.address)))
explore_LowLevelILInstruction(bv)
LLIL_UNDEF
0x1400b1d6c undefined
ret far 0xb18
LLIL_SET_REG
0x140001000 rsp = rsp - 0x28
sub rsp, 0x28
LLIL_SUB
0x140001000 rsp = rsp - 0x28
sub rsp, 0x28
LLIL_CONST_PTR
0x140001004 r8d = 4
mov r8d, 0x4
LLIL_CALL
0x140001018 call(0x140019390)
call 0x140019390
LLIL_ADD
0x140001024 rsp = rsp + 0x28
add rsp, 0x28
LLIL_TAILCALL
0x140001028 <return> tailcall(0x1400ea35c)
jmp 0x1400ea35c
LLIL_LOAD
0x14000130b call([0x14017e000].q)
call qword [rel 0x14017e000]
LLIL_PUSH
0x140001960 push(rbp)
push rbp
LLIL_REG
0x140001960 push(rbp)
push rbp
LLIL_CONST
0x140001971 r14d = 0
xor r14d, r14d
LLIL_STORE
0x140001974 [rbp + 0x38 {arg_10}].q = r14
mov qword [rbp+0x38], r14
LLIL_LOW_PART
0x140001978 ecx = (r14 + 0x18).d
lea ecx, [r14+0x18]
LLIL_IF
0x1400019df if ([0x14024f1c0].d s<= ecx) then 32 @ 0x140001a9c else 39 @ 0x1400019e5
jle 0x140001a9c
LLIL_CMP_SLE
0x1400019df if ([0x14024f1c0].d s<= ecx) then 32 @ 0x140001a9c else 39 @ 0x1400019e5
jle 0x140001a9c
LLIL_CMP_NE
0x1400019f8 if ([0x14024f1c0].d != -1) then 32 @ 0x140001a9c else 67 @ 0x1400019fe
jne 0x140001a9c
LLIL_CMP_E
0x140001c24 if ([0x1402488c0].q == 0) then 72 @ 0x140001c48 else 77 @ 0x140001c26
je 0x140001c48
LLIL_GOTO
0x140001c60 goto 107 @ 0x140001c61
nop
LLIL_ZX
0x140001a5d xmm1 = zx.o([0x140189cc0].q)
movsd xmm1, qword [rel 0x140189cc0]
LLIL_CMP_SGE
0x140001d0b if (eax s>= 0) then 185 @ 0x140001c91 else 187 @ 0x140001d0d
jns 0x140001c91
LLIL_NORET
0x140001d0d noreturn
call qword [rel 0x14017e750]
LLIL_POP
0x140001cfe r14 = pop
pop r14
LLIL_RET
0x14000367e <return> jump(pop)
retn
LLIL_XOR
0x1400038b8 rax = rax ^ rsp
xor rax, rsp
LLIL_CMP_SLT
0x14000777e if (eax s< 0) then 15 @ 0x140007807 else 18 @ 0x140007784
js 0x140007807
LLIL_SET_FLAG
0x1400078b5 cond:0 = temp1.d s>= 0
test eax, eax
LLIL_FLAG
0x140007904 if (cond:0) then 37 @ 0x1400078d4 else 64 @ 0x140007906
jns 0x1400078ce
LLIL_CMP_UGE
0x140007928 [0x14024c960].b = [0x14024c938].q u>= -1
setae byte [rel 0x14024c960]
LLIL_CMP_UGT
0x14000793e [0x14024c961].b = [0x14024c938].q u> rax
seta byte [rel 0x14024c961]
LLIL_CMP_ULT
0x1400079ba if ([0x14024c938].q u< rax) then 7 @ 0x140007a89 else 9 @ 0x1400079c0
jb 0x140007a89
LLIL_SET_REG_SPLIT
0x14000bf04 rdx:rax = mulu.dp.q(rax, rbx)
mul rbx
LLIL_MULU_DP
0x14000bf04 rdx:rax = mulu.dp.q(rax, rbx)
mul rbx
LLIL_CMP_ULE
0x14000c042 cond:0 = rax u<= rcx
cmp rax, rcx
LLIL_BP
0x14000c33c breakpoint
int3
LLIL_OR
0x14000d8f6 eax = eax | 1
or eax, 0x1
LLIL_TEST_BIT
0x14000edf7 flag:c = test_bit(r14d, 7)
bts r14d, 0x7
LLIL_AND
0x14000ef63 r14d = r14d & 0xfffffffb
and r14d, 0xfffffffb
LLIL_NOT
0x14000fdcb if (not(flag:z)) then 67 @ 0x14000fde5 else 72 @ 0x14000fdcd
jne 0x14000fde5
LLIL_LSL
0x140010fbb rcx = rcx << 4
shl rcx, 0x4
LLIL_LSR
0x140011c0f rsi = rsi u>> 1
shr rsi, 0x1
LLIL_ASR
0x14001237a rdx = rdx s>> 3
sar rdx, 0x3
LLIL_SX
0x140012690 rcx = sx.q([rcx + 0x18].d)
movsxd rcx, dword [rcx+0x18]
LLIL_NEG
0x140015799 r8d = neg.d(r8d)
neg r8d
LLIL_TRAP
0x140017d15 trap(0xd)
int 0x29
LLIL_MULS_DP
0x14001b3b6 rdx:rax = muls.dp.q(rax, rcx)
imul rcx
LLIL_MUL
0x14001b496 r14 = r9 * 0x78
imul r14, r9, 0x78
LLIL_CMP_SGT
0x14001c754 if (r15d s> 0xb) then 372 @ 0x14001c791 else 373 @ 0x14001c756
jg 0x14001c78d
LLIL_FLOAT_TO_INT
0x14001df0b rax = int.q(ftrunc(fconvert.t([rbp + 0xd8 {var_90}].q)))
cvttsd2si rax, qword [rbp+0xd8]
LLIL_DIVU_DP
0x14001e858 temp0.d = divu.dp.d(temp3.d:temp4.d, temp2.d)
div r10d
LLIL_MODU_DP
0x14001e858 temp1.d = modu.dp.d(temp5.d:temp6.d, temp2.d)
div r10d
LLIL_INT_TO_FLOAT
0x1400239b4 xmm0.q = float.d(rax)
cvtsi2sd xmm0, rax
LLIL_FADD
0x1400239b9 xmm0.q = xmm0.q f+ xmm0.q
addsd xmm0, xmm0
LLIL_FMUL
0x1400239cb xmm0.q = xmm0.q f* fconvert.t([0x1401a2d48].q)
mulsd xmm0, qword [rel 0x1401a2d48]
LLIL_FDIV
0x1400239fb xmm0.q = xmm0.q f/ xmm1.q
divsd xmm0, xmm1
LLIL_SBB
0x14002617d eax = sbb.d(eax, eax, flag:c)
sbb eax, eax
LLIL_INTRINSIC
0x14002f8a6 xmm0 = _mm_cvtepi32_pd(xmm0.q)
cvtdq2pd xmm0, xmm0
LLIL_CALL_PARAM
0x14002f8a6 xmm0 = _mm_cvtepi32_pd(xmm0.q)
cvtdq2pd xmm0, xmm0
LLIL_FCMP_UO
0x14002f8aa flag:p = is_unordered.q(xmm7.q, xmm0.q)
comisd xmm7, xmm0
LLIL_ROL
0x1400ea089 rcx = rol.q(rcx, 0x10)
rol rcx, 0x10
LLIL_ROR
0x1400ea095 rcx = ror.q(rcx, 0x10)
ror rcx, 0x10
LLIL_JUMP
0x140032306 jump(rcx)
jmp rcx
LLIL_FSUB
0x1400356af xmm1.q = xmm1.q f- xmm0.q
subsd xmm1, xmm0
LLIL_DIVS_DP
0x140037cd1 temp0.q = divs.dp.q(rdx:rax, rbx)
idiv rbx
LLIL_MODS_DP
0x140037cd1 temp1.q = mods.dp.q(rdx:rax, rbx)
idiv rbx
LLIL_JUMP_TO
0x14003b4e5 jump(rcx => 167 @ 0x14003b4e7, 170 @ 0x14003b4f1, 174 @ 0x14003b4ff, 178 @ 0x14003b50d, 182 @ 0x14003b51b, 186 @ 0x14003b529)
jmp rcx
Function 0x14006e370 at 0x14006e5fb has HLIL condition that exceeds maximum complexity, omitting condition (step 90)
LLIL_UNDEF
0x1400b1d6c undefined
ret far 0xb18
LLIL_ROL
0x1400ea089 rcx = rol.q(rcx, 0x10)
rol rcx, 0x10
LLIL_ROR
0x1400ea095 rcx = ror.q(rcx, 0x10)
ror rcx, 0x10
func = bv.get_functions_containing(here)[0]
for block in func.low_level_il.basic_blocks:
for instr in block:
if isinstance(instr, LowLevelILInstruction):
tt = instr.operation
print("Instruction")
print(binaryninja.LowLevelILOperation(tt).name)
print("\t0x%x %s" % (instr.address, instr))
print("\t%s" % (bv.get_disassembly(instr.address)))
for oper in instr.operands:
if isinstance(oper, LowLevelILInstruction):
tt = oper.operation
print("Operand:")
print(binaryninja.LowLevelILOperation(tt).name)
print("\t0x%x %s" % (instr.address, instr))
print("\t%s" % (bv.get_disassembly(instr.address)))