def method2dot(mx, tainted1=None, tainted2=None, tainted3=None, annotation=None, variables=None, variables_total=None, colors={}): """ Export analysis method to dot format @param mx : MethodAnalysis object @param colors : MethodAnalysis object @rtype : dot format buffer (it is a subgraph (dict)) """ tainted1 = tainted1 or {} tainted2 = tainted2 or {} tainted3 = tainted3 or {} annotation = annotation or {} variables = variables or {} variables_total = variables_total or {} colors = colors or { "true_branch": "green", "false_branch": "red", "default_branch": "purple", "jump_branch": "blue", "bg_idx": "lightgray", "idx": "blue", "bg_start_idx": "yellow", "bg_instruction": "lightgray", "instruction_name": "black", "instructions_operands": "yellow", "raw": "red", "string": "red", "literal": "green", "offset": "#4000FF", "method": "#DF3A01", "field": "#088A08", "type": "#0000FF", "registers_range": ("#999933", "#6666FF") } node_tpl = "\nstruct_%s [label=<\n<TABLE BORDER=\"2\" CELLBORDER=\"0\" CELLSPACING=\"3\" >\n%s</TABLE>>];\n" #STYLE=\"ROUNDED\" # v first tainting stuff v second tainting stuff v third tainting stuff v annotation v variables label_tpl = "<TR><TD ALIGN=\"LEFT\" BGCOLOR=\"%s\"> <FONT FACE=\"Times-Bold\" color=\"%s\">%x</FONT> </TD><TD ALIGN=\"RIGHT\" BGCOLOR=\"%s\"> %s </TD><TD ALIGN=\"RIGHT\" BGCOLOR=\"%s\"> %s </TD><TD ALIGN=\"RIGHT\" BGCOLOR=\"%s\"> %s </TD><TD ALIGN=\"RIGHT\"> %s </TD><TD ALIGN=\"LEFT\"> %s </TD><TD ALIGN=\"LEFT\" BGCOLOR=\"%s\"> <FONT FACE=\"Times-Bold\" color=\"%s\">%s </FONT> %s </TD></TR>\n" link_tpl = "<TR><TD PORT=\"%s\"></TD></TR>\n" edges_html = "" blocks_html = "" method = mx.get_method() sha256 = hashlib.sha256( "%s%s%s" % (mx.get_method().get_class_name(), mx.get_method().get_name(), mx.get_method().get_descriptor())).hexdigest() registers = {} if method.get_code(): for i in range(method.get_code().get_registers_size()): registers[i] = 0 #for DVMBasicMethodBlock in mx.basic_blocks.gets(): # ins_idx = DVMBasicMethodBlock.start # loop over method instructions # for DVMBasicMethodBlockInstruction in DVMBasicMethodBlock.get_instructions(): # operands = DVMBasicMethodBlockInstruction.get_operands(ins_idx) # for register in operands: # if register[0] == 0: # if register[1] not in registers: # registers[register[1]] = 0 # registers[register[1]] += 1 if registers: registers_colors = color_range(colors["registers_range"][0], colors["registers_range"][1], len(registers)) for i in registers: registers[i] = registers_colors.pop(0) new_links = [] params = [] method_information = method.get_information() if method_information: if "params" in method_information: for register, _ in method_information["params"]: params.append('v' + str(register)) for DVMBasicMethodBlock in mx.basic_blocks.gets(): ins_idx = DVMBasicMethodBlock.start block_id = hashlib.md5(sha256 + DVMBasicMethodBlock.name).hexdigest() content = link_tpl % 'header' for DVMBasicMethodBlockInstruction in DVMBasicMethodBlock.get_instructions( ): if DVMBasicMethodBlockInstruction.get_op_value( ) == 0x2b or DVMBasicMethodBlockInstruction.get_op_value() == 0x2c: new_links.append( (DVMBasicMethodBlock, ins_idx, DVMBasicMethodBlockInstruction.get_ref_off() * 2 + ins_idx)) elif DVMBasicMethodBlockInstruction.get_op_value() == 0x26: new_links.append( (DVMBasicMethodBlock, ins_idx, DVMBasicMethodBlockInstruction.get_ref_off() * 2 + ins_idx)) operands = DVMBasicMethodBlockInstruction.get_operands(ins_idx) output = ", ".join(mx.get_vm().get_operand_html( i, registers, colors, escape, textwrap.wrap) for i in operands) if ins_idx in tainted1: output_tainted1 = ", ".join( [i for i in tainted1[ins_idx][1] if i not in params]) params_tainted1 = [ i for i in tainted1[ins_idx][1] if i in params ] if output_tainted1 and params_tainted1: output_tainted1 += " | " if params_tainted1: output_tainted1 += "<FONT color=\"red\">" + ", ".join( params_tainted1) + "</FONT>" else: output_tainted1 = '' if ins_idx in tainted2: output_tainted2 = ", ".join( [i for i in tainted2[ins_idx][1] if i not in params]) params_tainted2 = [ i for i in tainted2[ins_idx][1] if i in params ] if output_tainted2 and params_tainted2: output_tainted2 += " | " if params_tainted2: output_tainted2 += "<FONT color=\"red\">" + ", ".join( params_tainted2) + "</FONT>" else: output_tainted2 = '' if ins_idx in tainted3: output_tainted3 = ", ".join( [i for i in tainted3[ins_idx][1] if i not in params]) params_tainted3 = [ i for i in tainted3[ins_idx][1] if i in params ] if output_tainted3 and params_tainted3: output_tainted3 += " | " if params_tainted3: output_tainted3 += "<FONT color=\"red\">" + ", ".join( params_tainted3) + "</FONT>" else: output_tainted3 = '' if ins_idx in annotation: temp = [] for bla, lol in annotation[ins_idx].items(): temp.append("%s: %s" % (bla, ", ".join(lol))) output_annotation = "; ".join(temp) else: output_annotation = '' if ins_idx in variables: output_variables = ", ".join(sorted(variables[ins_idx])) else: output_variables = '' formatted_operands = DVMBasicMethodBlockInstruction.get_formatted_operands( ) if formatted_operands: output += " ; %s" % str(formatted_operands) bg_idx = colors["bg_idx"] if ins_idx == 0 and "bg_start_idx" in colors: bg_idx = colors["bg_start_idx"] content += label_tpl % ( bg_idx, colors["idx"], ins_idx, colors["bg_instruction"], output_tainted1, colors["bg_instruction"], output_tainted2, colors["bg_instruction"], output_tainted3, output_annotation, output_variables, colors["bg_instruction"], colors["instruction_name"], DVMBasicMethodBlockInstruction.get_name(), output) ins_idx += DVMBasicMethodBlockInstruction.get_length() last_instru = DVMBasicMethodBlockInstruction # all blocks from one method parsed # updating dot HTML content content += link_tpl % 'tail' blocks_html += node_tpl % (block_id, content) # Block edges color treatment (conditional branchs colors) val = colors["true_branch"] if len(DVMBasicMethodBlock.childs) > 1: val = colors["false_branch"] elif len(DVMBasicMethodBlock.childs) == 1: val = colors["jump_branch"] values = None if (last_instru.get_op_value() == 0x2b or last_instru.get_op_value() == 0x2c) and len(DVMBasicMethodBlock.childs) > 1: val = colors["default_branch"] values = ["default"] values.extend( DVMBasicMethodBlock.get_special_ins( ins_idx - last_instru.get_length()).get_values()) # updating dot edges for DVMBasicMethodBlockChild in DVMBasicMethodBlock.childs: label_edge = "" if values: label_edge = values.pop(0) child_id = hashlib.md5( sha256 + DVMBasicMethodBlockChild[-1].name).hexdigest() edges_html += "struct_%s:tail -> struct_%s:header [penwidth=\"2\",color=\"%s\", label=\"%s\"];\n" % ( block_id, child_id, val, label_edge) # color switch if val == colors["false_branch"]: val = colors["true_branch"] elif val == colors["default_branch"]: val = colors["true_branch"] exception_analysis = DVMBasicMethodBlock.get_exception_analysis() if exception_analysis: for exception_elem in exception_analysis.exceptions: exception_block = exception_elem[-1] if exception_block: exception_id = hashlib.md5( sha256 + exception_block.name).hexdigest() edges_html += "struct_%s:tail -> struct_%s:header [penwidth=\"2\",color=\"%s\", label=\"%s\"];\n" % ( block_id, exception_id, "black", exception_elem[0]) for link in new_links: DVMBasicMethodBlock = link[0] DVMBasicMethodBlockChild = mx.basic_blocks.get_basic_block(link[2]) if DVMBasicMethodBlockChild: block_id = hashlib.md5(sha256 + DVMBasicMethodBlock.name).hexdigest() child_id = hashlib.md5(sha256 + DVMBasicMethodBlockChild.name).hexdigest() edges_html += "struct_%s:tail -> struct_%s:header [penwidth=\"2\",color=\"%s\", label=\"data(0x%x) to @0x%x\", style=\"dashed\"];\n" % ( block_id, child_id, "yellow", link[1], link[2]) method_label = method.get_class_name() + "." + method.get_name( ) + "->" + method.get_descriptor() method_information = method.get_information() if method_information: method_label += "\\nLocal registers v%d ... v%d" % ( method_information["registers"][0], method_information["registers"][1]) if "params" in method_information: for register, rtype in method_information["params"]: method_label += "\\nparam v%d = %s" % (register, rtype) method_label += "\\nreturn = %s" % (method_information["return"]) method_label += "\\nTypes:\\n" for k, v in variables_total.items(): method_label += "%s: %s\\n" % (k, ", ".join(v)) method_label += "\\nMarked at -1:" if tainted1.get(-1): method_label += "\\nBackward: %s" % ", ".join(tainted1.get(-1)[1]) if tainted2.get(-1): method_label += "\\nForward: %s" % ", ".join(tainted2.get(-1)[1]) if tainted3.get(-1): method_label += "\\nCombined: %s" % ", ".join(tainted3.get(-1)[1]) return {'name': method_label, 'nodes': blocks_html, 'edges': edges_html}
def method2dot(mx, backward, forward, combined, annotations, types, types_total, colors={}): """ Export analysis method to dot format @param mx : MethodAnalysis object @param colors : MethodAnalysis object @rtype : dot format buffer (it is a subgraph (dict)) """ colors = colors or { "true_branch": "green", "false_branch": "red", "default_branch": "purple", "jump_branch": "blue", "bg_idx": "lightgray", "idx": "blue", "bg_start_idx": "yellow", "bg_instruction": "lightgray", "instruction_name": "black", "instructions_operands": "yellow", "raw": "red", "string": "red", "literal": "green", "offset": "#4000FF", "method": "#DF3A01", "field": "#088A08", "type": "#0000FF", "registers_range": ("#999933", "#6666FF") } node_tpl = "\nstruct_%s [label=<\n<TABLE BORDER=\"0\" CELLBORDER=\"0\" CELLSPACING=\"3\">\n%s</TABLE>>];\n" label_tpl = "<TR><TD ALIGN=\"LEFT\" BGCOLOR=\"%s\"> <FONT FACE=\"Times-Bold\" color=\"%s\">%x</FONT> </TD><TD ALIGN=\"LEFT\" BGCOLOR=\"%s\"> <FONT FACE=\"Times-Bold\" color=\"%s\">%s </FONT> %s </TD><td bgcolor=\"lightgray\">%s</td><td bgcolor=\"lightgray\">%s</td><td bgcolor=\"lightgray\">%s</td><td bgcolor=\"lightgray\">%s</td></TR>\n" link_tpl = "<TR><TD PORT=\"%s\"></TD></TR>\n" edges_html = "" blocks_html = "" method = mx.get_method() sha256 = hashlib.sha256( "%s%s%s" % (mx.get_method().get_class_name(), mx.get_method().get_name(), mx.get_method().get_descriptor())).hexdigest() registers = {} if method.get_code(): for DVMBasicMethodBlock in mx.basic_blocks.gets(): for DVMBasicMethodBlockInstruction in DVMBasicMethodBlock.get_instructions( ): operands = DVMBasicMethodBlockInstruction.get_operands(0) for register in operands: if register[0] == 0: if register[1] not in registers: registers[register[1]] = 0 registers[register[1]] += 1 # for i in range(method.get_code().get_registers_size()): # registers[i] = 0 if registers: registers_colors = color_range(colors["registers_range"][0], colors["registers_range"][1], len(registers)) for i in registers: registers[i] = registers_colors.pop(0) new_links = [] for DVMBasicMethodBlock in mx.basic_blocks.gets(): ins_idx = DVMBasicMethodBlock.start block_id = hashlib.md5(sha256 + DVMBasicMethodBlock.get_name()).hexdigest() content = link_tpl % 'header' for DVMBasicMethodBlockInstruction in DVMBasicMethodBlock.get_instructions( ): if DVMBasicMethodBlockInstruction.get_op_value( ) == 0x2b or DVMBasicMethodBlockInstruction.get_op_value() == 0x2c: new_links.append( (DVMBasicMethodBlock, ins_idx, DVMBasicMethodBlockInstruction.get_ref_off() * 2 + ins_idx)) elif DVMBasicMethodBlockInstruction.get_op_value() == 0x26: new_links.append( (DVMBasicMethodBlock, ins_idx, DVMBasicMethodBlockInstruction.get_ref_off() * 2 + ins_idx)) operands = DVMBasicMethodBlockInstruction.get_operands(ins_idx) output = ", ".join(mx.get_vm().get_operand_html( i, registers, colors, escape, textwrap.wrap) for i in operands) formatted_operands = DVMBasicMethodBlockInstruction.get_formatted_operands( ) if formatted_operands: output += " ; %s" % str(formatted_operands) bg_idx = colors["bg_idx"] if ins_idx == 0 and "bg_start_idx" in colors: bg_idx = colors["bg_start_idx"] #print annotations.get(ins_idx) content += label_tpl % ( bg_idx, colors["idx"], ins_idx, colors["bg_instruction"], colors["instruction_name"], DVMBasicMethodBlockInstruction.get_name(), output, printhelper(forward, ins_idx), printhelper( backward, ins_idx), printhelper(combined, ins_idx), printhelperannotations(annotations, ins_idx)) ins_idx += DVMBasicMethodBlockInstruction.get_length() last_instru = DVMBasicMethodBlockInstruction # all blocks from one method parsed # updating dot HTML content content += link_tpl % 'tail' blocks_html += node_tpl % (block_id, content) # Block edges color treatment (conditional branchs colors) val = colors["true_branch"] if len(DVMBasicMethodBlock.childs) > 1: val = colors["false_branch"] elif len(DVMBasicMethodBlock.childs) == 1: val = colors["jump_branch"] values = None if (last_instru.get_op_value() == 0x2b or last_instru.get_op_value() == 0x2c) and len(DVMBasicMethodBlock.childs) > 1: val = colors["default_branch"] values = ["default"] values.extend( DVMBasicMethodBlock.get_special_ins( ins_idx - last_instru.get_length()).get_values()) # updating dot edges for DVMBasicMethodBlockChild in DVMBasicMethodBlock.childs: label_edge = "" if values: label_edge = values.pop(0) child_id = hashlib.md5( sha256 + DVMBasicMethodBlockChild[-1].get_name()).hexdigest() edges_html += "struct_%s:tail -> struct_%s:header [color=\"%s\", label=\"%s\"];\n" % ( block_id, child_id, val, label_edge) # color switch if val == colors["false_branch"]: val = colors["true_branch"] elif val == colors["default_branch"]: val = colors["true_branch"] exception_analysis = DVMBasicMethodBlock.get_exception_analysis() if exception_analysis: for exception_elem in exception_analysis.exceptions: exception_block = exception_elem[-1] if exception_block: exception_id = hashlib.md5( sha256 + exception_block.get_name()).hexdigest() edges_html += "struct_%s:tail -> struct_%s:header [color=\"%s\", label=\"%s\"];\n" % ( block_id, exception_id, "black", exception_elem[0]) for link in new_links: DVMBasicMethodBlock = link[0] DVMBasicMethodBlockChild = mx.basic_blocks.get_basic_block(link[2]) if DVMBasicMethodBlockChild: block_id = hashlib.md5(sha256 + DVMBasicMethodBlock.get_name()).hexdigest() child_id = hashlib.md5( sha256 + DVMBasicMethodBlockChild.get_name()).hexdigest() edges_html += "struct_%s:tail -> struct_%s:header [color=\"%s\", label=\"data(0x%x) to @0x%x\", style=\"dashed\"];\n" % ( block_id, child_id, "yellow", link[1], link[2]) method_label = method.get_class_name() + "." + method.get_name( ) + "->" + method.get_descriptor() method_information = method.get_information() if method_information: method_label += "\\nLocal registers v%d ... v%d" % ( method_information["registers"][0], method_information["registers"][1]) if "params" in method_information: for register, rtype in method_information["params"]: method_label += "\\nparam v%d = %s" % (register, rtype) method_label += "\\nreturn = %s" % (method_information["return"]) return {'name': method_label, 'nodes': blocks_html, 'edges': edges_html}
def method2dot(mx, colors={}): """ Export analysis method to dot format @param mx : MethodAnalysis object @param colors : MethodAnalysis object @rtype : dot format buffer (it is a subgraph (dict)) """ colors = colors or {"true_branch": "green", "false_branch": "red", "default_branch": "purple", "jump_branch": "blue", "bg_idx": "lightgray", "idx": "blue", "bg_start_idx": "yellow", "bg_instruction": "lightgray", "instruction_name": "black", "instructions_operands": "yellow", "raw": "red", "string": "red", "literal": "green", "offset": "#4000FF", "method": "#DF3A01", "field": "#088A08", "type": "#0000FF", "registers_range": ("#999933", "#6666FF") } node_tpl = "\nstruct_%s [label=<\n<TABLE BORDER=\"0\" CELLBORDER=\"0\" CELLSPACING=\"3\">\n%s</TABLE>>];\n" label_tpl = "<TR><TD ALIGN=\"LEFT\" BGCOLOR=\"%s\"> <FONT FACE=\"Times-Bold\" color=\"%s\">%x</FONT> </TD><TD ALIGN=\"LEFT\" BGCOLOR=\"%s\"> <FONT FACE=\"Times-Bold\" color=\"%s\">%s </FONT> %s </TD></TR>\n" link_tpl = "<TR><TD PORT=\"%s\"></TD></TR>\n" edges_html = "" blocks_html = "" method = mx.get_method() sha256 = hashlib.sha256("%s%s%s" % (mx.get_method().get_class_name(), mx.get_method().get_name(), mx.get_method().get_descriptor())).hexdigest() registers = {} if method.get_code(): for DVMBasicMethodBlock in mx.basic_blocks.gets(): for DVMBasicMethodBlockInstruction in DVMBasicMethodBlock.get_instructions(): operands = DVMBasicMethodBlockInstruction.get_operands(0) for register in operands: if register[0] == 0: if register[1] not in registers: registers[register[1]] = 0 registers[register[1]] += 1 # for i in range(method.get_code().get_registers_size()): # registers[i] = 0 if registers: registers_colors = color_range(colors["registers_range"][0], colors["registers_range"][1], len(registers)) for i in registers: registers[i] = registers_colors.pop(0) new_links = [] for DVMBasicMethodBlock in mx.basic_blocks.gets(): ins_idx = DVMBasicMethodBlock.start block_id = hashlib.md5(sha256 + DVMBasicMethodBlock.get_name()).hexdigest() content = link_tpl % 'header' for DVMBasicMethodBlockInstruction in DVMBasicMethodBlock.get_instructions(): if DVMBasicMethodBlockInstruction.get_op_value() == 0x2b or DVMBasicMethodBlockInstruction.get_op_value() == 0x2c: new_links.append((DVMBasicMethodBlock, ins_idx, DVMBasicMethodBlockInstruction.get_ref_off() * 2 + ins_idx)) elif DVMBasicMethodBlockInstruction.get_op_value() == 0x26: new_links.append((DVMBasicMethodBlock, ins_idx, DVMBasicMethodBlockInstruction.get_ref_off() * 2 + ins_idx)) operands = DVMBasicMethodBlockInstruction.get_operands(ins_idx) output = ", ".join(mx.get_vm().get_operand_html(i, registers, colors, escape, textwrap.wrap) for i in operands) formatted_operands = DVMBasicMethodBlockInstruction.get_formatted_operands() if formatted_operands: output += " ; %s" % str(formatted_operands) bg_idx = colors["bg_idx"] if ins_idx == 0 and "bg_start_idx" in colors: bg_idx = colors["bg_start_idx"] content += label_tpl % (bg_idx, colors["idx"], ins_idx, colors["bg_instruction"], colors["instruction_name"], DVMBasicMethodBlockInstruction.get_name(), output) ins_idx += DVMBasicMethodBlockInstruction.get_length() last_instru = DVMBasicMethodBlockInstruction # all blocks from one method parsed # updating dot HTML content content += link_tpl % 'tail' blocks_html += node_tpl % (block_id, content) # Block edges color treatment (conditional branchs colors) val = colors["true_branch"] if len(DVMBasicMethodBlock.childs) > 1: val = colors["false_branch"] elif len(DVMBasicMethodBlock.childs) == 1: val = colors["jump_branch"] values = None if (last_instru.get_op_value() == 0x2b or last_instru.get_op_value() == 0x2c) and len(DVMBasicMethodBlock.childs) > 1: val = colors["default_branch"] values = ["default"] values.extend(DVMBasicMethodBlock.get_special_ins(ins_idx - last_instru.get_length()).get_values()) # updating dot edges for DVMBasicMethodBlockChild in DVMBasicMethodBlock.childs: label_edge = "" if values: label_edge = values.pop(0) child_id = hashlib.md5(sha256 + DVMBasicMethodBlockChild[-1].get_name()).hexdigest() edges_html += "struct_%s:tail -> struct_%s:header [color=\"%s\", label=\"%s\"];\n" % (block_id, child_id, val, label_edge) # color switch if val == colors["false_branch"]: val = colors["true_branch"] elif val == colors["default_branch"]: val = colors["true_branch"] exception_analysis = DVMBasicMethodBlock.get_exception_analysis() if exception_analysis: for exception_elem in exception_analysis.exceptions: exception_block = exception_elem[-1] if exception_block: exception_id = hashlib.md5(sha256 + exception_block.get_name()).hexdigest() edges_html += "struct_%s:tail -> struct_%s:header [color=\"%s\", label=\"%s\"];\n" % (block_id, exception_id, "black", exception_elem[0]) for link in new_links: DVMBasicMethodBlock = link[0] DVMBasicMethodBlockChild = mx.basic_blocks.get_basic_block(link[2]) if DVMBasicMethodBlockChild: block_id = hashlib.md5(sha256 + DVMBasicMethodBlock.get_name()).hexdigest() child_id = hashlib.md5(sha256 + DVMBasicMethodBlockChild.get_name()).hexdigest() edges_html += "struct_%s:tail -> struct_%s:header [color=\"%s\", label=\"data(0x%x) to @0x%x\", style=\"dashed\"];\n" % (block_id, child_id, "yellow", link[1], link[2]) method_label = method.get_class_name() + "." + method.get_name() + "->" + method.get_descriptor() method_information = method.get_information() if method_information: method_label += "\\nLocal registers v%d ... v%d" % (method_information["registers"][0], method_information["registers"][1]) if "params" in method_information: for register, rtype in method_information["params"]: method_label += "\\nparam v%d = %s" % (register, rtype) method_label += "\\nreturn = %s" % (method_information["return"]) return {'name': method_label, 'nodes': blocks_html, 'edges': edges_html}
def method2dot(mx, colors={}): """ Export analysis method to dot format @param mx : MethodAnalysis object @param colors : MethodAnalysis object @rtype : dot format buffer (it is a subgraph (dict)) """ colors = colors or { 'true_branch': 'green', 'false_branch': 'red', 'default_branch': 'purple', 'jump_branch': 'blue', 'bg_idx': 'lightgray', 'idx': 'blue', 'bg_start_idx': 'yellow', 'bg_instruction': 'lightgray', 'instruction_name': 'black', 'instructions_operands': 'yellow', 'raw': 'red', 'string': 'red', 'literal': 'green', 'offset': '#4000FF', 'method': '#DF3A01', 'field': '#088A08', 'type': '#0000FF', 'registers_range': ('#999933', '#6666FF'), } node_tpl = \ ''' struct_%s [label=< <TABLE BORDER="0" CELLBORDER="0" CELLSPACING="3"> %s</TABLE>>]; ''' label_tpl = \ '<TR><TD ALIGN="LEFT" BGCOLOR="%s"> <FONT FACE="Times-Bold" color="%s">%x</FONT> </TD><TD ALIGN="LEFT" BGCOLOR="%s"> <FONT FACE="Times-Bold" color="%s">%s </FONT> %s </TD></TR>\n' link_tpl = '<TR><TD PORT="%s"></TD></TR>\n' edges_html = '' blocks_html = '' method = mx.get_method_novm() sha256 = hashlib.sha256( '%s%s%s' % (mx.get_method_novm().get_class_name(), mx.get_method_novm().get_name(), mx.get_method_novm().get_descriptor())).hexdigest() registers = {} if method.get_code(): for DVMBasicMethodBlock in mx.basic_blocks.gets(): for DVMBasicMethodBlockInstruction in \ DVMBasicMethodBlock.get_instructions(): operands = \ DVMBasicMethodBlockInstruction.get_operands(0) for register in operands: if register[0] == 0: if register[1] not in registers: registers[register[1]] = 0 registers[register[1]] += 1 # for i in range(method.get_code().get_registers_size()): # registers[i] = 0 if registers: registers_colors = color_range(colors['registers_range'][0], colors['registers_range'][1], len(registers)) for i in registers: registers[i] = registers_colors.pop(0) new_links = [] for DVMBasicMethodBlock in mx.basic_blocks.gets(): ins_idx = DVMBasicMethodBlock.start block_id = hashlib.md5(sha256 + DVMBasicMethodBlock.get_name()).hexdigest() content = link_tpl % 'header' for DVMBasicMethodBlockInstruction in \ DVMBasicMethodBlock.get_instructions(): if DVMBasicMethodBlockInstruction.get_op_value() == 0x2b \ or DVMBasicMethodBlockInstruction.get_op_value() \ == 0x2c: new_links.append( (DVMBasicMethodBlock, ins_idx, DVMBasicMethodBlockInstruction.get_ref_off() * 2 + ins_idx)) elif DVMBasicMethodBlockInstruction.get_op_value() == 0x26: new_links.append( (DVMBasicMethodBlock, ins_idx, DVMBasicMethodBlockInstruction.get_ref_off() * 2 + ins_idx)) operands = \ DVMBasicMethodBlockInstruction.get_operands(ins_idx) output = ', '.join(mx.get_vm().get_operand_html( i, registers, colors, escape, textwrap.wrap) for i in operands) formatted_operands = \ DVMBasicMethodBlockInstruction.get_formatted_operands() if formatted_operands: output += ' ; %s' % str(formatted_operands) bg_idx = colors['bg_idx'] if ins_idx == 0 and 'bg_start_idx' in colors: bg_idx = colors['bg_start_idx'] content += label_tpl % ( bg_idx, colors['idx'], ins_idx, colors['bg_instruction'], colors['instruction_name'], DVMBasicMethodBlockInstruction.get_name(), output, ) ins_idx += DVMBasicMethodBlockInstruction.get_length() last_instru = DVMBasicMethodBlockInstruction # all blocks from one method parsed # updating dot HTML content content += link_tpl % 'tail' blocks_html += node_tpl % (block_id, content) # Block edges color treatment (conditional branchs colors) val = colors['true_branch'] if len(DVMBasicMethodBlock.childs) > 1: val = colors['false_branch'] elif len(DVMBasicMethodBlock.childs) == 1: val = colors['jump_branch'] values = None if (last_instru.get_op_value() == 0x2b or last_instru.get_op_value() == 0x2c) \ and len(DVMBasicMethodBlock.childs) > 1: val = colors['default_branch'] values = ['default'] values.extend( DVMBasicMethodBlock.get_special_ins( ins_idx - last_instru.get_length()).get_values()) # updating dot edges for DVMBasicMethodBlockChild in DVMBasicMethodBlock.childs: label_edge = '' if values: label_edge = values.pop(0) child_id = hashlib.md5( sha256 + DVMBasicMethodBlockChild[-1].get_name()).hexdigest() edges_html += \ 'struct_%s:tail -> struct_%s:header [color="%s", label="%s"];\n' \ % (block_id, child_id, val, label_edge) # color switch if val == colors['false_branch']: val = colors['true_branch'] elif val == colors['default_branch']: val = colors['true_branch'] exception_analysis = \ DVMBasicMethodBlock.get_exception_analysis() if exception_analysis: for exception_elem in exception_analysis.exceptions: exception_block = exception_elem[-1] if exception_block: exception_id = hashlib.md5( sha256 + exception_block.get_name()).hexdigest() edges_html += \ 'struct_%s:tail -> struct_%s:header [color="%s", label="%s"];\n' \ % (block_id, exception_id, 'black', exception_elem[0]) for link in new_links: DVMBasicMethodBlock = link[0] DVMBasicMethodBlockChild = \ mx.basic_blocks.get_basic_block(link[2]) if DVMBasicMethodBlockChild: block_id = hashlib.md5(sha256 + DVMBasicMethodBlock.get_name()).hexdigest() child_id = hashlib.md5( sha256 + DVMBasicMethodBlockChild.get_name()).hexdigest() edges_html += \ 'struct_%s:tail -> struct_%s:header [color="%s", label="data(0x%x) to @0x%x", style="dashed"];\n' \ % (block_id, child_id, 'yellow', link[1], link[2]) method_label = method.get_class_name() + '.' + method.get_name() \ + '->' + method.get_descriptor() method_information = method.get_information() if method_information: method_label += '\\nLocal registers v%d ... v%d' \ % (method_information['registers'][0], method_information['registers'][1]) if 'params' in method_information: for (register, rtype) in method_information['params']: method_label += '\\nparam v%d = %s' % (register, rtype) method_label += '\\nreturn = %s' % method_information['return'] return {'name': method_label, 'nodes': blocks_html, 'edges': edges_html}
def method2dot(mx, colors={}): """ Export analysis method to dot format @param mx : MethodAnalysis object @param colors : MethodAnalysis object @rtype : dot format buffer (it is a subgraph (dict)) """ colors = colors or { 'true_branch': 'green', 'false_branch': 'red', 'default_branch': 'purple', 'jump_branch': 'blue', 'bg_idx': 'lightgray', 'idx': 'blue', 'bg_start_idx': 'yellow', 'bg_instruction': 'lightgray', 'instruction_name': 'black', 'instructions_operands': 'yellow', 'raw': 'red', 'string': 'red', 'literal': 'green', 'offset': '#4000FF', 'method': '#DF3A01', 'field': '#088A08', 'type': '#0000FF', 'registers_range': ('#999933', '#6666FF'), } node_tpl = \ ''' struct_%s [label=< <TABLE BORDER="0" CELLBORDER="0" CELLSPACING="3"> %s</TABLE>>]; ''' label_tpl = \ '<TR><TD ALIGN="LEFT" BGCOLOR="%s"> <FONT FACE="Times-Bold" color="%s">%x</FONT> </TD><TD ALIGN="LEFT" BGCOLOR="%s"> <FONT FACE="Times-Bold" color="%s">%s </FONT> %s </TD></TR>\n' link_tpl = '<TR><TD PORT="%s"></TD></TR>\n' edges_html = '' blocks_html = '' method = mx.get_method_novm() sha256 = hashlib.sha256('%s%s%s' % (mx.get_method_novm().get_class_name(), mx.get_method_novm().get_name(), mx.get_method_novm().get_descriptor())).hexdigest() registers = {} if method.get_code(): for DVMBasicMethodBlock in mx.basic_blocks.gets(): for DVMBasicMethodBlockInstruction in \ DVMBasicMethodBlock.get_instructions(): operands = \ DVMBasicMethodBlockInstruction.get_operands(0) for register in operands: if register[0] == 0: if register[1] not in registers: registers[register[1]] = 0 registers[register[1]] += 1 # for i in range(method.get_code().get_registers_size()): # registers[i] = 0 if registers: registers_colors = color_range(colors['registers_range'][0], colors['registers_range'][1], len(registers)) for i in registers: registers[i] = registers_colors.pop(0) new_links = [] for DVMBasicMethodBlock in mx.basic_blocks.gets(): ins_idx = DVMBasicMethodBlock.start block_id = hashlib.md5(sha256 + DVMBasicMethodBlock.get_name()).hexdigest() content = link_tpl % 'header' for DVMBasicMethodBlockInstruction in \ DVMBasicMethodBlock.get_instructions(): if DVMBasicMethodBlockInstruction.get_op_value() == 0x2b \ or DVMBasicMethodBlockInstruction.get_op_value() \ == 0x2c: new_links.append((DVMBasicMethodBlock, ins_idx, DVMBasicMethodBlockInstruction.get_ref_off() * 2 + ins_idx)) elif DVMBasicMethodBlockInstruction.get_op_value() == 0x26: new_links.append((DVMBasicMethodBlock, ins_idx, DVMBasicMethodBlockInstruction.get_ref_off() * 2 + ins_idx)) operands = \ DVMBasicMethodBlockInstruction.get_operands(ins_idx) output = ', '.join(mx.get_vm().get_operand_html(i, registers, colors, escape, textwrap.wrap) for i in operands) formatted_operands = \ DVMBasicMethodBlockInstruction.get_formatted_operands() if formatted_operands: output += ' ; %s' % str(formatted_operands) bg_idx = colors['bg_idx'] if ins_idx == 0 and 'bg_start_idx' in colors: bg_idx = colors['bg_start_idx'] content += label_tpl % ( bg_idx, colors['idx'], ins_idx, colors['bg_instruction'], colors['instruction_name'], DVMBasicMethodBlockInstruction.get_name(), output, ) ins_idx += DVMBasicMethodBlockInstruction.get_length() last_instru = DVMBasicMethodBlockInstruction # all blocks from one method parsed # updating dot HTML content content += link_tpl % 'tail' blocks_html += node_tpl % (block_id, content) # Block edges color treatment (conditional branchs colors) val = colors['true_branch'] if len(DVMBasicMethodBlock.childs) > 1: val = colors['false_branch'] elif len(DVMBasicMethodBlock.childs) == 1: val = colors['jump_branch'] values = None if (last_instru.get_op_value() == 0x2b or last_instru.get_op_value() == 0x2c) \ and len(DVMBasicMethodBlock.childs) > 1: val = colors['default_branch'] values = ['default'] values.extend(DVMBasicMethodBlock.get_special_ins(ins_idx - last_instru.get_length()).get_values()) # updating dot edges for DVMBasicMethodBlockChild in DVMBasicMethodBlock.childs: label_edge = '' if values: label_edge = values.pop(0) child_id = hashlib.md5(sha256 + DVMBasicMethodBlockChild[-1].get_name()).hexdigest() edges_html += \ 'struct_%s:tail -> struct_%s:header [color="%s", label="%s"];\n' \ % (block_id, child_id, val, label_edge) # color switch if val == colors['false_branch']: val = colors['true_branch'] elif val == colors['default_branch']: val = colors['true_branch'] exception_analysis = \ DVMBasicMethodBlock.get_exception_analysis() if exception_analysis: for exception_elem in exception_analysis.exceptions: exception_block = exception_elem[-1] if exception_block: exception_id = hashlib.md5(sha256 + exception_block.get_name()).hexdigest() edges_html += \ 'struct_%s:tail -> struct_%s:header [color="%s", label="%s"];\n' \ % (block_id, exception_id, 'black', exception_elem[0]) for link in new_links: DVMBasicMethodBlock = link[0] DVMBasicMethodBlockChild = \ mx.basic_blocks.get_basic_block(link[2]) if DVMBasicMethodBlockChild: block_id = hashlib.md5(sha256 + DVMBasicMethodBlock.get_name()).hexdigest() child_id = hashlib.md5(sha256 + DVMBasicMethodBlockChild.get_name()).hexdigest() edges_html += \ 'struct_%s:tail -> struct_%s:header [color="%s", label="data(0x%x) to @0x%x", style="dashed"];\n' \ % (block_id, child_id, 'yellow', link[1], link[2]) method_label = method.get_class_name() + '.' + method.get_name() \ + '->' + method.get_descriptor() method_information = method.get_information() if method_information: method_label += '\\nLocal registers v%d ... v%d' \ % (method_information['registers'][0], method_information['registers'][1]) if 'params' in method_information: for (register, rtype) in method_information['params']: method_label += '\\nparam v%d = %s' % (register, rtype) method_label += '\\nreturn = %s' % method_information['return'] return {'name': method_label, 'nodes': blocks_html, 'edges': edges_html}
def method2dot(mx, tainted1=None, tainted2=None, tainted3=None, annotation=None, variables=None, variables_total=None, colors={}): """ Export analysis method to dot format @param mx : MethodAnalysis object @param colors : MethodAnalysis object @rtype : dot format buffer (it is a subgraph (dict)) """ tainted1 = tainted1 or {} tainted2 = tainted2 or {} tainted3 = tainted3 or {} annotation = annotation or {} variables = variables or {} variables_total = variables_total or {} colors = colors or {"true_branch": "green", "false_branch": "red", "default_branch": "purple", "jump_branch": "blue", "bg_idx": "lightgray", "idx": "blue", "bg_start_idx": "yellow", "bg_instruction": "lightgray", "instruction_name": "black", "instructions_operands": "yellow", "raw": "red", "string": "red", "literal": "green", "offset": "#4000FF", "method": "#DF3A01", "field": "#088A08", "type": "#0000FF", "registers_range": ("#999933", "#6666FF") } node_tpl = "\nstruct_%s [label=<\n<TABLE BORDER=\"2\" CELLBORDER=\"0\" CELLSPACING=\"3\" >\n%s</TABLE>>];\n"#STYLE=\"ROUNDED\" # v first tainting stuff v second tainting stuff v third tainting stuff v annotation v variables label_tpl = "<TR><TD ALIGN=\"LEFT\" BGCOLOR=\"%s\"> <FONT FACE=\"Times-Bold\" color=\"%s\">%x</FONT> </TD><TD ALIGN=\"RIGHT\" BGCOLOR=\"%s\"> %s </TD><TD ALIGN=\"RIGHT\" BGCOLOR=\"%s\"> %s </TD><TD ALIGN=\"RIGHT\" BGCOLOR=\"%s\"> %s </TD><TD ALIGN=\"RIGHT\"> %s </TD><TD ALIGN=\"LEFT\"> %s </TD><TD ALIGN=\"LEFT\" BGCOLOR=\"%s\"> <FONT FACE=\"Times-Bold\" color=\"%s\">%s </FONT> %s </TD></TR>\n" link_tpl = "<TR><TD PORT=\"%s\"></TD></TR>\n" edges_html = "" blocks_html = "" method = mx.get_method() sha256 = hashlib.sha256("%s%s%s" % (mx.get_method().get_class_name(), mx.get_method().get_name(), mx.get_method().get_descriptor())).hexdigest() registers = {} if method.get_code(): for i in range(method.get_code().get_registers_size()): registers[i] = 0 #for DVMBasicMethodBlock in mx.basic_blocks.gets(): # ins_idx = DVMBasicMethodBlock.start # loop over method instructions # for DVMBasicMethodBlockInstruction in DVMBasicMethodBlock.get_instructions(): # operands = DVMBasicMethodBlockInstruction.get_operands(ins_idx) # for register in operands: # if register[0] == 0: # if register[1] not in registers: # registers[register[1]] = 0 # registers[register[1]] += 1 if registers: registers_colors = color_range(colors["registers_range"][0], colors["registers_range"][1], len(registers)) for i in registers: registers[i] = registers_colors.pop(0) new_links = [] params = [] method_information = method.get_information() if method_information: if "params" in method_information: for register, _ in method_information["params"]: params.append('v'+str(register)) for DVMBasicMethodBlock in mx.basic_blocks.gets(): ins_idx = DVMBasicMethodBlock.start block_id = hashlib.md5(sha256 + DVMBasicMethodBlock.name).hexdigest() content = link_tpl % 'header' for DVMBasicMethodBlockInstruction in DVMBasicMethodBlock.get_instructions(): if DVMBasicMethodBlockInstruction.get_op_value() == 0x2b or DVMBasicMethodBlockInstruction.get_op_value() == 0x2c: new_links.append((DVMBasicMethodBlock, ins_idx, DVMBasicMethodBlockInstruction.get_ref_off() * 2 + ins_idx)) elif DVMBasicMethodBlockInstruction.get_op_value() == 0x26: new_links.append((DVMBasicMethodBlock, ins_idx, DVMBasicMethodBlockInstruction.get_ref_off() * 2 + ins_idx)) operands = DVMBasicMethodBlockInstruction.get_operands(ins_idx) output = ", ".join(mx.get_vm().get_operand_html(i, registers, colors, escape, textwrap.wrap) for i in operands) if ins_idx in tainted1: output_tainted1 = ", ".join([i for i in tainted1[ins_idx][1] if i not in params]) params_tainted1 = [i for i in tainted1[ins_idx][1] if i in params] if output_tainted1 and params_tainted1: output_tainted1 += " | " if params_tainted1: output_tainted1 += "<FONT color=\"red\">"+", ".join(params_tainted1)+"</FONT>" else: output_tainted1 = '' if ins_idx in tainted2: output_tainted2 = ", ".join([i for i in tainted2[ins_idx][1] if i not in params]) params_tainted2 = [i for i in tainted2[ins_idx][1] if i in params] if output_tainted2 and params_tainted2: output_tainted2 += " | " if params_tainted2: output_tainted2 += "<FONT color=\"red\">"+", ".join(params_tainted2)+"</FONT>" else: output_tainted2 = '' if ins_idx in tainted3: output_tainted3 = ", ".join([i for i in tainted3[ins_idx][1] if i not in params]) params_tainted3 = [i for i in tainted3[ins_idx][1] if i in params] if output_tainted3 and params_tainted3: output_tainted3 += " | " if params_tainted3: output_tainted3 += "<FONT color=\"red\">"+", ".join(params_tainted3)+"</FONT>" else: output_tainted3 = '' if ins_idx in annotation: temp = [] for bla, lol in annotation[ins_idx].items(): temp.append("%s: %s" % (bla, ", ".join(lol))) output_annotation = "; ".join(temp) else: output_annotation = '' if ins_idx in variables: output_variables = ", ".join(sorted(variables[ins_idx])) else: output_variables = '' formatted_operands = DVMBasicMethodBlockInstruction.get_formatted_operands() if formatted_operands: output += " ; %s" % str(formatted_operands) bg_idx = colors["bg_idx"] if ins_idx == 0 and "bg_start_idx" in colors: bg_idx = colors["bg_start_idx"] content += label_tpl % (bg_idx, colors["idx"], ins_idx, colors["bg_instruction"], output_tainted1, colors["bg_instruction"], output_tainted2, colors["bg_instruction"], output_tainted3, output_annotation, output_variables, colors["bg_instruction"], colors["instruction_name"], DVMBasicMethodBlockInstruction.get_name(), output) ins_idx += DVMBasicMethodBlockInstruction.get_length() last_instru = DVMBasicMethodBlockInstruction # all blocks from one method parsed # updating dot HTML content content += link_tpl % 'tail' blocks_html += node_tpl % (block_id, content) # Block edges color treatment (conditional branchs colors) val = colors["true_branch"] if len(DVMBasicMethodBlock.childs) > 1: val = colors["false_branch"] elif len(DVMBasicMethodBlock.childs) == 1: val = colors["jump_branch"] values = None if (last_instru.get_op_value() == 0x2b or last_instru.get_op_value() == 0x2c) and len(DVMBasicMethodBlock.childs) > 1: val = colors["default_branch"] values = ["default"] values.extend(DVMBasicMethodBlock.get_special_ins(ins_idx - last_instru.get_length()).get_values()) # updating dot edges for DVMBasicMethodBlockChild in DVMBasicMethodBlock.childs: label_edge = "" if values: label_edge = values.pop(0) child_id = hashlib.md5(sha256 + DVMBasicMethodBlockChild[-1].name).hexdigest() edges_html += "struct_%s:tail -> struct_%s:header [penwidth=\"2\",color=\"%s\", label=\"%s\"];\n" % (block_id, child_id, val, label_edge) # color switch if val == colors["false_branch"]: val = colors["true_branch"] elif val == colors["default_branch"]: val = colors["true_branch"] exception_analysis = DVMBasicMethodBlock.get_exception_analysis() if exception_analysis: for exception_elem in exception_analysis.exceptions: exception_block = exception_elem[-1] if exception_block: exception_id = hashlib.md5(sha256 + exception_block.name).hexdigest() edges_html += "struct_%s:tail -> struct_%s:header [penwidth=\"2\",color=\"%s\", label=\"%s\"];\n" % (block_id, exception_id, "black", exception_elem[0]) for link in new_links: DVMBasicMethodBlock = link[0] DVMBasicMethodBlockChild = mx.basic_blocks.get_basic_block(link[2]) if DVMBasicMethodBlockChild: block_id = hashlib.md5(sha256 + DVMBasicMethodBlock.name).hexdigest() child_id = hashlib.md5(sha256 + DVMBasicMethodBlockChild.name).hexdigest() edges_html += "struct_%s:tail -> struct_%s:header [penwidth=\"2\",color=\"%s\", label=\"data(0x%x) to @0x%x\", style=\"dashed\"];\n" % (block_id, child_id, "yellow", link[1], link[2]) method_label = method.get_class_name() + "." + method.get_name() + "->" + method.get_descriptor() method_information = method.get_information() if method_information: method_label += "\\nLocal registers v%d ... v%d" % (method_information["registers"][0], method_information["registers"][1]) if "params" in method_information: for register, rtype in method_information["params"]: method_label += "\\nparam v%d = %s" % (register, rtype) method_label += "\\nreturn = %s" % (method_information["return"]) method_label += "\\nTypes:\\n" for k, v in variables_total.items(): method_label += "%s: %s\\n" % (k, ", ".join(v)) method_label += "\\nMarked at -1:" if tainted1.get(-1): method_label += "\\nBackward: %s" % ", ".join(tainted1.get(-1)[1]) if tainted2.get(-1): method_label += "\\nForward: %s" % ", ".join(tainted2.get(-1)[1]) if tainted3.get(-1): method_label += "\\nCombined: %s" % ", ".join(tainted3.get(-1)[1]) return {'name': method_label, 'nodes': blocks_html, 'edges': edges_html}