Example #1
0
 def __iter__(self):
     count = ctypes.c_ulonglong()
     lines = core.BNGetFlowGraphNodeLines(self.handle, count)
     block = self.basic_block
     try:
         for i in range(0, count.value):
             addr = lines[i].addr
             if (lines[i].instrIndex != 0xffffffffffffffff) and (
                     block is not None) and hasattr(block, 'il_function'):
                 il_instr = block.il_function[lines[i].instrIndex]
             else:
                 il_instr = None
             tokens = []
             for j in range(0, lines[i].count):
                 token_type = InstructionTextTokenType(
                     lines[i].tokens[j].type)
                 text = lines[i].tokens[j].text
                 value = lines[i].tokens[j].value
                 size = lines[i].tokens[j].size
                 operand = lines[i].tokens[j].operand
                 context = lines[i].tokens[j].context
                 confidence = lines[i].tokens[j].confidence
                 address = lines[i].tokens[j].address
                 tokens.append(
                     function.InstructionTextToken(token_type, text, value,
                                                   size, operand, context,
                                                   address, confidence))
             yield function.DisassemblyTextLine(tokens, addr, il_instr)
     finally:
         core.BNFreeDisassemblyTextLines(lines, count.value)
Example #2
0
 def lines(self):
     """Flow graph block list of text lines"""
     count = ctypes.c_ulonglong()
     lines = core.BNGetFlowGraphNodeLines(self.handle, count)
     block = self.basic_block
     result = []
     for i in range(0, count.value):
         addr = lines[i].addr
         if (lines[i].instrIndex != 0xffffffffffffffff) and (
                 block is not None) and hasattr(block, 'il_function'):
             il_instr = block.il_function[lines[i].instrIndex]
         else:
             il_instr = None
         color = highlight.HighlightColor._from_core_struct(
             lines[i].highlight)
         tokens = []
         for j in range(0, lines[i].count):
             token_type = InstructionTextTokenType(lines[i].tokens[j].type)
             text = lines[i].tokens[j].text
             value = lines[i].tokens[j].value
             size = lines[i].tokens[j].size
             operand = lines[i].tokens[j].operand
             context = lines[i].tokens[j].context
             confidence = lines[i].tokens[j].confidence
             address = lines[i].tokens[j].address
             tokens.append(
                 function.InstructionTextToken(token_type, text, value,
                                               size, operand, context,
                                               address, confidence))
         result.append(
             function.DisassemblyTextLine(tokens, addr, il_instr, color))
     core.BNFreeDisassemblyTextLines(lines, count.value)
     return result
def find_jump_table(bv, addr):
    for block in bv.get_basic_blocks_at(addr):
        func = block.function
        arch = func.arch
        addrsize = arch.address_size

        # Grab the instruction tokens so that we can look for the table's starting address
        tokens, length = arch.get_instruction_text(bv.read(addr, 16), addr)

        # Look for the next jump instruction, which may be the current instruction. Some jump tables will
        # compute the address first then jump to the computed address as a separate instruction.
        jump_addr = addr
        while jump_addr < block.end:
            info = arch.get_instruction_info(bv.read(jump_addr, 16), jump_addr)
            if len(info.branches) != 0:
                break
            jump_addr += info.length
        if jump_addr >= block.end:
            print "Unable to find jump after instruction 0x%x" % addr
            continue
        print "Jump at 0x%x" % jump_addr

        # Collect the branch targets for any tables referenced by the clicked instruction
        branches = []
        for token in tokens:
            if InstructionTextTokenType(
                    token.type
            ) == InstructionTextTokenType.PossibleAddressToken:  # Table addresses will be a "possible address" token
                tbl = token.value
                print "Found possible table at 0x%x" % tbl
                i = 0
                while True:
                    # Read the next pointer from the table
                    data = bv.read(tbl + (i * addrsize), addrsize)
                    if len(data) == addrsize:
                        if addrsize == 4:
                            ptr = struct.unpack("<I", data)[0]
                        else:
                            ptr = struct.unpack("<Q", data)[0]

                        # If the pointer is within the binary, add it as a destination and continue
                        # to the next entry
                        if (ptr >= bv.start) and (ptr < bv.end):
                            print "Found destination 0x%x" % ptr
                            branches.append((arch, ptr))
                        else:
                            # Once a value that is not a pointer is encountered, the jump table is ended
                            break
                    else:
                        # Reading invalid memory
                        break

                    i += 1

        # Set the indirect branch targets on the jump instruction to be the list of targets discovered
        func.set_user_indirect_branches(jump_addr, branches)
Example #4
0
	def get_disassembly_text(self, settings=None):
		"""
		``get_disassembly_text`` returns a list of binaryninja.function.DisassemblyTextLine objects for the current basic block.

		:param DisassemblySettings settings: (optional) DisassemblySettings object
		:Example:

			>>> current_basic_block.get_disassembly_text()
			[<0x100000f30: _main:>, <0x100000f30: push    rbp>, ... ]
		"""
		settings_obj = None
		if settings:
			settings_obj = settings.handle

		count = ctypes.c_ulonglong()
		lines = core.BNGetBasicBlockDisassemblyText(self.handle, settings_obj, count)
		result = []
		for i in range(0, count.value):
			addr = lines[i].addr
			if (lines[i].instrIndex != 0xffffffffffffffff) and hasattr(self, 'il_function'):
				il_instr = self.il_function[lines[i].instrIndex]
			else:
				il_instr = None
			color = highlight.HighlightColor._from_core_struct(lines[i].highlight)
			tokens = []
			for j in range(0, lines[i].count):
				token_type = InstructionTextTokenType(lines[i].tokens[j].type)
				text = lines[i].tokens[j].text
				value = lines[i].tokens[j].value
				size = lines[i].tokens[j].size
				operand = lines[i].tokens[j].operand
				context = lines[i].tokens[j].context
				confidence = lines[i].tokens[j].confidence
				address = lines[i].tokens[j].address
				tokens.append(binaryninja.function.InstructionTextToken(token_type, text, value, size, operand, context, address, confidence))
			result.append(binaryninja.function.DisassemblyTextLine(tokens, addr, il_instr, color))
		core.BNFreeDisassemblyTextLines(lines, count.value)
		return result
Example #5
0
 def get_tokens_after_name(self, base_confidence=max_confidence):
     count = ctypes.c_ulonglong()
     platform = None
     if self.platform is not None:
         platform = self.platform.handle
     tokens = core.BNGetTypeTokensAfterName(self.handle, platform,
                                            base_confidence, count)
     result = []
     for i in range(0, count.value):
         token_type = InstructionTextTokenType(tokens[i].type)
         text = tokens[i].text
         value = tokens[i].value
         size = tokens[i].size
         operand = tokens[i].operand
         context = tokens[i].context
         confidence = tokens[i].confidence
         address = tokens[i].address
         result.append(
             binaryninja.function.InstructionTextToken(
                 token_type, text, value, size, operand, context, address,
                 confidence))
     core.BNFreeTokenList(tokens, count.value)
     return result
Example #6
0
def render_svg(function, origname):
    graph = function.create_graph()
    graph.layout_and_wait()
    heightconst = 15
    ratio = 0.48
    widthconst = heightconst * ratio

    output = '''<html>
	<head>
		<style type="text/css">
			@import url(https://fonts.googleapis.com/css?family=Source+Code+Pro);
			body {
				background-color: rgb(42, 42, 42);
                                color: rgb(220, 220, 220);
                                font-family: "Source Code Pro", "Lucida Console", "Consolas", monospace;
			}
                        a, a:visited  {
                                color: rgb(200, 200, 200);
                                font-weight: bold;
                        }
			svg {
				background-color: rgb(42, 42, 42);
				display: block;
				margin: 0 auto;
			}
			.basicblock {
				stroke: rgb(224, 224, 224);
			}
			.edge {
				fill: none;
				stroke-width: 1px;
			}
			.back_edge {
				fill: none;
				stroke-width: 2px;
			}
			.UnconditionalBranch, .IndirectBranch {
				stroke: rgb(128, 198, 233);
				color: rgb(128, 198, 233);
			}
			.FalseBranch {
				stroke: rgb(222, 143, 151);
				color: rgb(222, 143, 151);
			}
			.TrueBranch {
				stroke: rgb(162, 217, 175);
				color: rgb(162, 217, 175);
			}
			.arrow {
				stroke-width: 1;
				fill: currentColor;
			}
			text {
                                font-family: "Source Code Pro", "Lucida Console", "Consolas", monospace;
				font-size: 9pt;
				fill: rgb(224, 224, 224);
			}
			.CodeSymbolToken {
				fill: rgb(128, 198, 223);
			}
			.DataSymbolToken {
				fill: rgb(142, 230, 237);
			}
			.TextToken, .InstructionToken, .BeginMemoryOperandToken, .EndMemoryOperandToken {
				fill: rgb(224, 224, 224);
			}
			.PossibleAddressToken, .IntegerToken {
				fill: rgb(162, 217, 175);
			}
			.RegisterToken {
				fill: rgb(237, 223, 179);
			}
			.AnnotationToken {
				fill: rgb(218, 196, 209);
			}
			.ImportToken {
				fill: rgb(237, 189, 129);
			}
			.StackVariableToken {
				fill: rgb(193, 220, 199);
			}
		</style>
		<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.2/jquery.min.js"></script>
	</head>
'''
    output += '''<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="{width}" height="{height}">
		<defs>
			<marker id="arrow-TrueBranch" class="arrow TrueBranch" viewBox="0 0 10 10" refX="10" refY="5" markerUnits="strokeWidth" markerWidth="8" markerHeight="6" orient="auto">
				<path d="M 0 0 L 10 5 L 0 10 z" />
			</marker>
			<marker id="arrow-FalseBranch" class="arrow FalseBranch" viewBox="0 0 10 10" refX="10" refY="5" markerUnits="strokeWidth" markerWidth="8" markerHeight="6" orient="auto">
				<path d="M 0 0 L 10 5 L 0 10 z" />
			</marker>
			<marker id="arrow-UnconditionalBranch" class="arrow UnconditionalBranch" viewBox="0 0 10 10" refX="10" refY="5" markerUnits="strokeWidth" markerWidth="8" markerHeight="6" orient="auto">
				<path d="M 0 0 L 10 5 L 0 10 z" />
			</marker>
			<marker id="arrow-IndirectBranch" class="arrow IndirectBranch" viewBox="0 0 10 10" refX="10" refY="5" markerUnits="strokeWidth" markerWidth="8" markerHeight="6" orient="auto">
				<path d="M 0 0 L 10 5 L 0 10 z" />
			</marker>
		</defs>
	'''.format(width=graph.width * widthconst + 20,
            height=graph.height * heightconst + 20)
    output += '''	<g id="functiongraph0" class="functiongraph">
			<title>Function Graph 0</title>
	'''
    edges = ''
    for i, block in enumerate(graph.blocks):

        # Calculate basic block location and coordinates
        x = ((block.x) * widthconst)
        y = ((block.y) * heightconst)
        width = ((block.width) * widthconst)
        height = ((block.height) * heightconst)

        # Render block
        output += '		<g id="basicblock{i}">\n'.format(i=i)
        output += '			<title>Basic Block {i}</title>\n'.format(i=i)
        rgb = colors['none']
        try:
            bb = block.basic_block
            color_code = bb.highlight.color
            color_str = bb.highlight._standard_color_to_str(color_code)
            if color_str in colors:
                rgb = colors[color_str]
        except:
            pass
        output += '			<rect class="basicblock" x="{x}" y="{y}" fill-opacity="0.4" height="{height}" width="{width}" fill="rgb({r},{g},{b})"/>\n'.format(
            x=x,
            y=y,
            width=width + 16,
            height=height + 12,
            r=rgb[0],
            g=rgb[1],
            b=rgb[2])

        # Render instructions, unfortunately tspans don't allow copying/pasting more
        # than one line at a time, need SVG 1.2 textarea tags for that it looks like

        output += '			<text x="{x}" y="{y}">\n'.format(x=x,
                                                       y=y +
                                                       (i + 1) * heightconst)
        for i, line in enumerate(block.lines):
            output += '				<tspan id="instr-{address}" x="{x}" y="{y}">'.format(
                x=x + 6,
                y=y + 6 + (i + 0.7) * heightconst,
                address=hex(line.address)[:-1])
            hover = instruction_data_flow(function, line.address)
            output += '<title>{hover}</title>'.format(hover=hover)
            for token in line.tokens:
                # TODO: add hover for hex, function, and reg tokens
                output += '<tspan class="{tokentype}">{text}</tspan>'.format(
                    text=escape(token.text),
                    tokentype=InstructionTextTokenType(token.type).name)
            output += '</tspan>\n'
        output += '			</text>\n'
        output += '		</g>\n'

        # Edges are rendered in a seperate chunk so they have priority over the
        # basic blocks or else they'd render below them

        for edge in block.outgoing_edges:
            points = ""
            x, y = edge.points[0]
            points += str(
                x * widthconst) + "," + str(y * heightconst + 12) + " "
            for x, y in edge.points[1:-1]:
                points += str(x * widthconst) + "," + str(
                    y * heightconst) + " "
            x, y = edge.points[-1]
            points += str(
                x * widthconst) + "," + str(y * heightconst + 0) + " "
            if edge.back_edge:
                edges += '		<polyline class="back_edge {type}" points="{points}" marker-end="url(#arrow-{type})"/>\n'.format(
                    type=BranchType(edge.type).name, points=points)
            else:
                edges += '		<polyline class="edge {type}" points="{points}" marker-end="url(#arrow-{type})"/>\n'.format(
                    type=BranchType(edge.type).name, points=points)
    output += ' ' + edges + '\n'
    output += '	</g>\n'
    output += '</svg>'

    output += '<p>This CFG generated by <a href="https://binary.ninja/">Binary Ninja</a> from {filename} on {timestring}.</p>'.format(
        filename=origname, timestring=time.strftime("%c"))
    output += '</html>'
    return output