Recently picked up Binary Ninja and been playing around with it. Here are a few scripts/plugins I've made that others may find useful.
You can find all of them in plugin form here: https://github.com/SlidyBat/binja-plugins
For makesig/rtti you can also add them as snippets rather than plugins since they are single-file.
makesig
Spoiler
Pretty much a port of asherkin's makesig.idc for IDA. May generate slightly different signatures; this plugin only wildcards addresses that may be relocated rather than all addresses.
Also allows searching for AM style signatures since there's no equivalent functionality in Binja.
# Store non-wildcarded start of signature
sig_start = ''
for c in sig:
if c == '*': break
sig_start += c
curr_search = bv.start
while True:
curr_search = bv.find_next_data(curr_search + 1, sig_start, FindFlag.FindCaseSensitive)
if curr_search == None:
break
br.offset = curr_search
for i in range(len(sig)):
byte = br.read8()
if byte == None:
break
if sig[i] != '*' and ord(sig[i]) != byte:
break
else:
results += [curr_search]
if len(results) >= max_results:
return results
def find_sig_from_input(bv):
sig = interaction.get_text_line_input('Signature:', 'Enter signature to search for...')
addrs = find_sig(bv, decode_sig(sig.strip()), max_results=100)
if len(addrs) == 0:
print('No matches found for signature')
else:
print('Found match at 0x%x' % addrs[0])
sig = ''
br = BinaryReader(bv)
br.seek(func_start)
while br.offset < func_end:
curr_instr = br.offset
instr_len = bv.get_instruction_length(curr_instr)
for i in range(instr_len):
relocations = bv.relocation_ranges_at(br.offset)
# Wildcard bytes that will be relocated
if len(relocations) == 0:
sig += chr(br.read8())
else:
sig += '*'
if is_good_sig(bv, sig):
print(encode_sig(sig))
return
br.offset = curr_instr + instr_len
print('Function too short to generate unique signature')
PluginCommand.register("Find signature", "Searches the current binary for the given signature", find_sig_from_input)
PluginCommand.register_for_function("Make signature for current function", "Generates a unique signature for the current selected function", sig_for_function)
# Now that we have the class name, rename complete object locator to something more suitable
bv.define_user_symbol(Symbol(SymbolType.DataSymbol, p_col, 'locator_%s' % class_name))
bv.define_user_symbol(Symbol(SymbolType.DataSymbol, col, '%s::`RTTI Complete Object Locator\'' % class_name))
# Define base class array
br.seek(classhier + 8)
num_baseclasses = br.read32()
baseclasses = read_ptr(bv, br)
bv.define_data_var(baseclasses, Type.array(Type.pointer(bv.arch, base_class_desc_t(bv)), num_baseclasses))
bv.define_user_symbol(Symbol(SymbolType.DataSymbol, baseclasses, '%s::`RTTI Base Class Array\'' % class_name))
# Count number of functions in vtable and mark as array
br.seek(p_vtable)
vfunc_count = 0
while True:
vtable_func = read_ptr(bv, br)
if not is_vtable_func(bv, vtable_func):
break
vfunc_count += 1
bv.add_function(vtable_func)
bv.define_data_var(p_vtable, vtable_t(bv, vfunc_count))
bv.define_user_symbol(Symbol(SymbolType.DataSymbol, p_vtable, vtable_name))
# The last vtable func check failed, back up in case this is a locator
br.offset -= 4
PluginCommand.register('Scan RTTI', 'Scans for MSVC RTTI', command_scan_rtti)
SMX
Spoiler
This is more of a fun project than a practical one. It adds support for analysing .smx files, including defining the internal structures, decompressing/unpacking code/data sections, disassembling, and lifting to LLIL.