Example #1
0
def quick_get_func(fpath='./tests', symbol='_fizzbuzz'):
    if sys.argv[1:]:
        fpath = sys.argv[1]
    if sys.argv[2:]:
        symbol = sys.argv[2]

    update_analysis = True
    callbacks = None
    options = {'analysis.mode': 'controlFlow'}  # minimal analysis for speed
    #bv = BinaryViewType.get_view_of_file(fpath)

    # prefer the .bndb, if it exists
    if os.path.exists(fpath + '.bndb'):
        fpath = fpath + '.bndb'
    if not os.path.exists(fpath):
        raise Exception('%s doesnt exist' % fpath)

    print('opening %s in binaryninja' % fpath)
    t0 = time.perf_counter()
    bv = binaryninja.open_view(fpath, update_analysis, callbacks, options)
    if not bv:
        raise Exception('binary ninja didnt return analysis on -%s-' % fpath)
    #bv.update_analysis_and_wait()
    #func = bv.get_functions_by_name(symbol)[0]
    t1 = time.perf_counter()
    print('analysis complete after %fs' % (t1 - t0))

    func = None
    if symbol:
        funcs = [f for f in bv.functions if f.name.lower() == symbol.lower()]
        if funcs:
            func = funcs[0]
    #if not funcs:
    #    raise Exception('binary ninja didnt return func on -%s-' % symbol)
    return (bv, func)
Example #2
0
bn.debuginfo.DebugInfoParser.register("dummy extra debug parser 2",
                                      lambda bv: bv.view_type != "Raw",
                                      lambda di, bv: None)

# Test fetching parser list and fetching by name
print(f"Availible parsers: {len(list(bn.debuginfo.DebugInfoParser))}")
for p in bn.debuginfo.DebugInfoParser:
    if p == parser:
        print(
            f"  {bn.debuginfo.DebugInfoParser[p.name].name} (the one we just registered)"
        )
    else:
        print(f"  {bn.debuginfo.DebugInfoParser[p.name].name}")

# Test calling our `is_valid` callback
bv = bn.open_view(filename,
                  options={"analysis.experimental.parseDebugInfo": False})
if parser.is_valid_for_view(bv):
    print("Parser is valid")
else:
    print("Parser is NOT valid!")
    quit()

# Test getting list of valid parsers, and DebugInfoParser's repr
print("")
for p in bn.debuginfo.DebugInfoParser.get_parsers_for_view(bv):
    print(f"`{p.name}` is valid for `{bv}`")
print("")

# Test calling our `parse_info` callback
debug_info = parser.parse_debug_info(bv)
# debug_info = bv.debug_info
Example #3
0
    fpath = sys.argv[1]

    wf = Workflow().clone('MyWorkflow')
    a = Activity('MyActivity', action=action_func)
    result = wf.register_activity(a)
    assert result == True

    # the topology as we expected?
    subactivities = wf.subactivities('core.function.basicAnalysis')
    assert subactivities[0] == 'core.function.generateLiftedIL'
    assert subactivities[1] == 'core.function.resetIndirectBranchesOnFullUpdate'

    # insert, finalize workflow
    result = wf.insert('core.function.resetIndirectBranchesOnFullUpdate', ['MyActivity'])
    assert result == True
    result = wf.register()
    assert result == True

    # did we change the topology as expected?
    subactivities = wf.subactivities('core.function.basicAnalysis')
    assert subactivities[0] == 'core.function.generateLiftedIL'
    assert subactivities[1] == 'MyActivity'
    assert subactivities[2] == 'core.function.resetIndirectBranchesOnFullUpdate'

    print('open_view()')

    bv = binaryninja.open_view(fpath, \
      options={'workflows.enable':True, 'workflows.functionWorkflow':'MyWorkflow'})

    print('done')  
Example #4
0
#!/usr/bin/env python

# do multiple binaries opened reference the same architecture instance?

import binaryninja

bv0 = binaryninja.open_view('/bin/ls')
assert bv0
bv1 = binaryninja.open_view('/bin/ln')
assert bv1
bv2 = binaryninja.open_view('/bin/cp')
assert bv2

print('binary views: %d %d %d' % (id(bv0), id(bv1), id(bv2)))

print('architectures: %d %d %d' % (id(bv0.arch), id(bv1.arch), id(bv2.arch)))

def main():
    with binaryninja.open_view("tdpServer") as bv:

        # Step 1. Check if our target has at least one source and one sink we care about
        source_symbols = []
        sink_symbols = []

        symbols = bv.get_symbols_of_type(
            binaryninja.SymbolType.ImportedFunctionSymbol)
        for symbol in symbols:
            if symbol.name in sources:
                source_symbols.append(symbol)
            elif symbol.name in sinks:
                sink_symbols.append(symbol)

        if (set(sinks) & set([sink.name for sink in sink_symbols])) and (
                set(sources) & set([source.name
                                    for source in source_symbols])):
            print(
                "This target contains interesting source(s) and sink(s). Continuing analysis..."
            )
        else:
            print(
                "This target does not contain interesting source(s) and sink(s). Done."
            )
            return

        # Step 2. Find functions that calls at least one source and one sink
        source_callers = []
        sink_callers = []
        interesting_functions = []

        for source in source_symbols:
            func = bv.get_function_at(source.address)
            source_callers.extend(func.callers)

        for sink in sink_symbols:
            func = bv.get_function_at(sink.address)
            sink_callers.extend(func.callers)

        interesting_functions = (set(source_callers) & set(sink_callers))

        if len(interesting_functions) <= 0:
            print("\nNo interesting functions found to analyze. Done.")
            return
        else:
            print("\nFound {} interesting functions to analyze:".format(
                len(interesting_functions)))
            for func in interesting_functions:
                print("  {}".format(func.name))

        # Step 3. Dig into interesting functions
        for func in interesting_functions:
            print("\nAnalyzing function: {}".format(func.name))

            source_args = []
            sink_args = []

            # using HLIL
            for bb in func.hlil:
                for ins in bb:
                    hlil_call_ins = None
                    if ins.operation == binaryninja.HighLevelILOperation.HLIL_CALL:
                        hlil_call_ins = ins
                    elif ins.operation == binaryninja.HighLevelILOperation.HLIL_ASSIGN and ins.src.operation == binaryninja.HighLevelILOperation.HLIL_CALL:
                        hlil_call_ins = ins.src
                    else:
                        continue

                    call_target = bv.get_function_at(
                        hlil_call_ins.dest.constant)
                    if call_target.name in sources:
                        param1 = hlil_call_ins.params[0]
                        print(" >> 0x{:x} : {}({}, ...)".format(
                            ins.address, call_target.name, param1))
                        if param1.operation == binaryninja.HighLevelILOperation.HLIL_ADDRESS_OF:
                            param1 = param1.src
                        source_args.append(param1.var)

                    elif call_target.name in sinks:
                        param1 = hlil_call_ins.params[0]
                        print(" >> 0x{:x} : {}({}, ...)".format(
                            ins.address, call_target.name, param1))
                        if param1.operation == binaryninja.HighLevelILOperation.HLIL_ADDRESS_OF:
                            param1 = param1.src
                        sink_args.append(param1.var)

            if len(set(sink_args) & set(source_args)) > 0:
                print(
                    "  [!] Alert: Function {} appears to contain a vulnerable `system` call pattern!"
                    .format(func.name))
Example #6
0
def main(target):
    with binaryninja.open_view(target) as bv:

        for sink in sinks:
            # 1. Find symbols we want to analyze
            symbols = []
            symbol_list = bv.get_symbols_by_name(sink)

            for symbol in symbol_list:
                if symbol.type == binaryninja.SymbolType.ImportedFunctionSymbol:
                    symbols.append(symbol)

            if len(symbols) <= 0:
                continue

            # 2. Find all cross references for each symbol
            for symbol in symbols:
                callers = bv.get_callers(symbol.address)
                if len(callers) <= 0:
                    continue
                for caller in callers:
                    func = caller.function
                    addr = caller.address

                    # 3. For each location where a sink is called, grab the parameters.
                    mlil_index = func.mlil.get_instruction_start(addr)
                    mlil_ins = func.mlil[mlil_index]
                    hlil_ins = mlil_ins.hlil
                    params = []
                    if hlil_ins.operation == binaryninja.HighLevelILOperation.HLIL_CALL:
                        params = hlil_ins.params

                    # 4. Isolate `format` parameter
                    if len(params) >= (sinks[sink] + 1):
                        fparam = params[sinks[sink]]
                        if fparam.expr_type and fparam.expr_type.const:
                            debug_print("0x{:08x} : {} is SAFE!".format(
                                hlil_ins.address, fparam))
                            continue

                        target_var = None
                        try:
                            if fparam.operation == binaryninja.HighLevelILOperation.HLIL_VAR:
                                target_var = fparam.var
                            elif fparam.operation == binaryninja.HighLevelILOperation.HLIL_DEREF:
                                target_var = fparam.src.var
                            else:
                                debug_print(
                                    ">> Unsupported type: {} at 0x{:08x}".
                                    format(fparam.operation.name,
                                           hlil_ins.address))
                                continue
                        except AttributeError as e:
                            debug_print(
                                ">> ERROR: 0x{:08x} : {}\n>> {}".format(
                                    hlil_ins.address, fparam, e))
                            continue

                        # 5. Locate definition (initialization) and uses of the `format` parameter
                        definitions = func.hlil.get_var_definitions(target_var)
                        uses = func.hlil.get_var_uses(target_var)
                        if len(uses) >= 1:
                            debug_print("\nFunction: {}".format(func.name))
                            for definition in definitions:
                                debug_print(
                                    "Def of {} at 0x{:x} - {} ({})".format(
                                        definition.dest, definition.address,
                                        definition, definition.operation.name))
                            for use in uses:
                                debug_print(
                                    "Use of {} at 0x{:x} - {} ({})".format(
                                        use.var, use.address, use.instr,
                                        use.instr.operation.name))

                                # 6. Check if our `format` parameter is used in a tracked `source` function, in the tracked paramater slot
                                if use.instr.operation == binaryninja.HighLevelILOperation.HLIL_CALL:
                                    if str(use.instr.dest) in sources:
                                        source_call_ins = use.instr.dest
                                        params = source_call_ins.params
                                        target_param_index = sources[str(
                                            use.instr.src.dest)]
                                        if len(params) >= (target_param_index +
                                                           1):
                                            target_param = params[
                                                target_param_index]
                                            if type(
                                                    target_param
                                            ) == binaryninja.function.Variable and p == target_var:
                                                print(
                                                    "ALERT! - Function: {} : 0x{:X}"
                                                    .format(
                                                        func.name, func.start))

                                elif use.instr.operation == binaryninja.HighLevelILOperation.HLIL_VAR_INIT:
                                    if str(use.instr.src.dest) in sources:
                                        source_call_ins = use.instr.src
                                        params = source_call_ins.params
                                        target_param_index = sources[str(
                                            use.instr.src.dest)]
                                        if len(params) >= (target_param_index +
                                                           1):
                                            target_param = params[
                                                target_param_index]
                                            for p in target_param.prefix_operands:
                                                if type(
                                                        p
                                                ) == binaryninja.function.Variable and p == target_var:
                                                    print(
                                                        "ALERT! - Function: {} : 0x{:X}"
                                                        .format(
                                                            func.name,
                                                            func.start))
Example #7
0
#!/usr/bin/env python3
# does Zain's new .in_loop attribute of BasicBlock work?

import sys
import binaryninja

fpath = (sys.argv[1:] and sys.argv[1]) or './tests'
symname = (sys.argv[2:] and sys.argv[2]) or '_some_loops'
bv = binaryninja.open_view(fpath, True, None, {'analysis.mode':'controlFlow'})

func = next((f for f in bv.functions if f.name == symname), None)
if not func:
    print('function %s not found, available are:' % symname)
    print(', '.join([f.name for f in bv.functions]))
    sys.exit(-1)

print('-------- analyzing function %s --------' % func.name)
for (i,bb) in enumerate(func.basic_blocks):
    print('b%d: %s.in_loop = %s' % (i, bb, bb.in_loop))
Example #8
0
int main()
{
  // printf takes a format string and prints it to standard out
  printf("Hello world!");

  // return 0 means that we ran correctly and have no errors
  return 0;
}
"""

# can we compile it to HLIL? (gecil = "good enough c to il")
good_enough_hlil_func, imaginary_memory_space = gecil(main_function_source)

# And, with a possible location for that function in the binary,
possible_binary_location = 0x401149
bv = bn.open_view("example")
bv.update_analysis_and_wait()
bn_func = bv.get_function_at(possible_binary_location)
hlil_func = bn_func.hlil

# can we match the graphs,
#  (here I'm demonstrating matching on basically an exact match,
#   because graph theory is hard, but also string arguments!)
match = True
instruction_generator = hlil_func.instructions
for geil in good_enough_hlil_func.instructions:
    if geil.operation is hlil.HighLevelILOperation.HLIL_COMMENT:
        continue

    bnil = next(instruction_generator)
Example #9
0
        result.append('\t%s["%s"]' % (block_id(block), label))

    # block identifier to block identifier
    for src in func.basic_blocks:
        for edge in src.outgoing_edges:
            dst = edge.target
            result.append('\t%s --> %s' % (block_id(src), block_id(dst)))

    return '\n'.join(result)

if __name__ == '__main__':
    fpath = '../testbins/tests-linux-x64-elf'
    if sys.argv[1:]:
        fpath = sys.argv[1]

    sym_name = 'collatz_message'
    if sys.argv[2:]:
        sym_name = sys.argv[2]
    sym_name = sym_name.lower()

    with binaryninja.open_view(fpath) as bview:
        functions = [f for f in bview.functions if f.name.lower() == sym_name]
        function = functions[0]

        print('```mermaid')
        print(func_to_mermaid(function))
        print('```') 



Example #10
0
bv.platform = plat
bv.add_function(0, plat=plat)
bv.update_analysis_and_wait()

assert len(bv.functions)==1
f = bv.functions[0]
print('IL available after creation:')
print_func(f)

bv.create_database('/tmp/tmp.bndb')

print('-------- IL available from .bndb with get_view_of_file(update_analysis=False)')
bv = binaryninja.BinaryViewType.get_view_of_file('/tmp/tmp.bndb', update_analysis=False)
assert len(bv.functions)==1
f = bv.functions[0]
print_func(f)

print('-------- IL available from .bndb with get_view_of_file(update_analysis=True)')
bv = binaryninja.BinaryViewType.get_view_of_file('/tmp/tmp.bndb', update_analysis=True)
assert len(bv.functions)==1
f = bv.functions[0]
print_func(f)

print('-------- IL available from .bndb with open_view()')
with binaryninja.open_view('/tmp/tmp.bndb') as bv:
    assert len(bv.functions)==1
    f = bv.functions[0]
    #f.reanalyze()
    print_func(f)

Example #11
0
import binaryninja
from miasm.core.graph import DiGraph

def bbid(bb):
    return 'b%d' % bb.index

def miasm_graph_from_binja(func):
    G = DiGraph()

    for src in func.basic_blocks:
        for dst in [edge.target for edge in src.outgoing_edges]:
            G.add_edge(bbid(src), bbid(dst))

    return G

bv = binaryninja.open_view(sys.argv[1], True, None, {'analysis.mode':'controlFlow'})

for func in bv.functions:
    print('-------- analyzing function %s --------' % func.name)

    # get binja's answer
    #
    answer_binja = set()
    for bb in func.basic_blocks:
        if bb.in_loop:
            answer_binja.add(bbid(bb))
    print('binja says:', answer_binja)

    # get miasm's answer
    #
    answer_miasm = set()
Example #12
0
# 1.474496s controlFlow (16.929012% of full)
# 2.059575s basic (23.646425% of full)
# 6.303724s intermediate (72.374422% of full)
# 8.709878s full (100.000000% of full)

import sys, time
import binaryninja

fpath = '/bin/ls' if len(sys.argv) == 1 else sys.argv[1]
update_analysis = True
callbacks = None
options = {}

# cause plugins to load, whatever else to get initialized which could interfere in measurements
print('initial open')
with binaryninja.open_view(fpath) as bv:
    pass

modes = ['controlFlow', 'basic', 'intermediate', 'full']
results = []

for mode in modes:
    options = {'analysis.mode': mode}
    print('opening with %s' % options)
    t0 = time.perf_counter()
    with binaryninja.open_view(fpath, update_analysis, callbacks,
                               options) as bv:
        t1 = time.perf_counter()
        results.append(t1 - t0)
        print('done! %fs' % results[-1])