class DvMethod(object): def __init__(self, methanalysis): method = methanalysis.get_method() self.method = method self.start_block = next(methanalysis.get_basic_blocks().get(), None) self.cls_name = method.get_class_name() self.name = method.get_name() self.lparams = [] self.var_to_name = defaultdict() self.writer = None self.graph = None self.ast = None self.access = util.get_access_method(method.get_access_flags()) desc = method.get_descriptor() self.type = desc.split(')')[-1] self.params_type = util.get_params_type(desc) self.triple = method.get_triple() self.exceptions = methanalysis.exceptions.exceptions code = method.get_code() if code is None: logger.debug('No code : %s %s', self.name, self.cls_name) else: start = code.registers_size - code.ins_size if 'static' not in self.access: self.var_to_name[start] = ThisParam(start, self.cls_name) self.lparams.append(start) start += 1 num_param = 0 for ptype in self.params_type: param = start + num_param self.lparams.append(param) self.var_to_name[param] = Param(param, ptype) num_param += util.get_type_size(ptype) if not __debug__: from androguard.core import bytecode bytecode.method2png('/tmp/dad/graphs/%s#%s.png' % \ (self.cls_name.split('/')[-1][:-1], self.name), methanalysis) def process(self, doAST=False): logger.debug('METHOD : %s', self.name) # Native methods... no blocks. if self.start_block is None: logger.debug('Native Method.') if doAST: self.ast = JSONWriter(None, self).get_ast() else: self.writer = Writer(None, self) self.writer.write_method() return graph = construct(self.start_block, self.var_to_name, self.exceptions) self.graph = graph if not __debug__: util.create_png(self.cls_name, self.name, graph, '/tmp/dad/blocks') use_defs, def_uses = build_def_use(graph, self.lparams) split_variables(graph, self.var_to_name, def_uses, use_defs) dead_code_elimination(graph, def_uses, use_defs) register_propagation(graph, def_uses, use_defs) place_declarations(graph, self.var_to_name, def_uses, use_defs) del def_uses, use_defs # After the DCE pass, some nodes may be empty, so we can simplify the # graph to delete these nodes. # We start by restructuring the graph by spliting the conditional nodes # into a pre-header and a header part. split_if_nodes(graph) # We then simplify the graph by merging multiple statement nodes into # a single statement node when possible. This also delete empty nodes. simplify(graph) graph.compute_rpo() if not __debug__: util.create_png(self.cls_name, self.name, graph, '/tmp/dad/pre-structured') identify_structures(graph, graph.immediate_dominators()) if not __debug__: util.create_png(self.cls_name, self.name, graph, '/tmp/dad/structured') if doAST: self.ast = JSONWriter(graph, self).get_ast() else: self.writer = Writer(graph, self) self.writer.write_method() def get_ast(self): return self.ast def show_source(self): print(self.get_source()) def get_source(self): if self.writer: return '%s' % self.writer return '' def get_source_ext(self): if self.writer: return self.writer.str_ext() return [] def __repr__(self): #return 'Method %s' % self.name return 'class DvMethod(object): %s' % self.name
class DvMethod(object): def __init__(self, methanalysis): method = methanalysis.get_method() self.method = method self.start_block = next(methanalysis.get_basic_blocks().get(), None) self.cls_name = method.get_class_name() self.name = method.get_name() self.lparams = [] self.var_to_name = defaultdict() self.writer = None self.graph = None self.ast = None self.access = util.get_access_method(method.get_access_flags()) desc = method.get_descriptor() self.type = desc.split(')')[-1] self.params_type = util.get_params_type(desc) self.triple = method.get_triple() self.exceptions = methanalysis.exceptions.exceptions code = method.get_code() if code is None: logger.debug('No code : %s %s', self.name, self.cls_name) else: start = code.registers_size - code.ins_size if 'static' not in self.access: self.var_to_name[start] = ThisParam(start, self.cls_name) self.lparams.append(start) start += 1 num_param = 0 for ptype in self.params_type: param = start + num_param self.lparams.append(param) self.var_to_name[param] = Param(param, ptype) num_param += util.get_type_size(ptype) if not __debug__: from androguard.core import bytecode bytecode.method2png('/tmp/dad/graphs/%s#%s.png' % \ (self.cls_name.split('/')[-1][:-1], self.name), methanalysis) def process(self, doAST=False): logger.debug('METHOD : %s', self.name) # Native methods... no blocks. if self.start_block is None: logger.debug('Native Method.') if doAST: self.ast = JSONWriter(None, self).get_ast() else: self.writer = Writer(None, self) self.writer.write_method() return graph = construct(self.start_block, self.var_to_name, self.exceptions) self.graph = graph if not __debug__: util.create_png(self.cls_name, self.name, graph, '/tmp/dad/blocks') use_defs, def_uses = build_def_use(graph, self.lparams) split_variables(graph, self.var_to_name, def_uses, use_defs) dead_code_elimination(graph, def_uses, use_defs) register_propagation(graph, def_uses, use_defs) place_declarations(graph, self.var_to_name, def_uses, use_defs) del def_uses, use_defs # After the DCE pass, some nodes may be empty, so we can simplify the # graph to delete these nodes. # We start by restructuring the graph by spliting the conditional nodes # into a pre-header and a header part. split_if_nodes(graph) # We then simplify the graph by merging multiple statement nodes into # a single statement node when possible. This also delete empty nodes. simplify(graph) graph.compute_rpo() if not __debug__: util.create_png(self.cls_name, self.name, graph, '/tmp/dad/pre-structured') identify_structures(graph, graph.immediate_dominators()) if not __debug__: util.create_png(self.cls_name, self.name, graph, '/tmp/dad/structured') if doAST: self.ast = JSONWriter(graph, self).get_ast() else: self.writer = Writer(graph, self) self.writer.write_method() def get_ast(self): return self.ast def show_source(self): print self.get_source() def get_source(self): if self.writer: return '%s' % self.writer return '' def get_source_ext(self): if self.writer: return self.writer.str_ext() return [] def __repr__(self): #return 'Method %s' % self.name return 'class DvMethod(object): %s' % self.name
class DvMethod: """ This is a wrapper around :class:`~androguard.core.analysis.analysis.MethodAnalysis` and :class:`~androguard.core.bytecodes.dvm.EncodedMethod` inside the decompiler. """ def __init__(self, methanalysis): """ :param androguard.core.analysis.analysis.MethodAnalysis methanalysis: """ method = methanalysis.get_method() self.method = method self.start_block = next(methanalysis.get_basic_blocks().get(), None) self.cls_name = method.get_class_name() self.name = method.get_name() self.lparams = [] self.var_to_name = defaultdict() self.writer = None self.graph = None self.ast = None self.access = util.get_access_method(method.get_access_flags()) desc = method.get_descriptor() self.type = desc.split(')')[-1] self.params_type = util.get_params_type(desc) self.triple = method.get_triple() self.exceptions = methanalysis.exceptions.exceptions code = method.get_code() if code is None: logger.debug('No code : %s %s', self.name, self.cls_name) else: start = code.registers_size - code.ins_size if 'static' not in self.access: self.var_to_name[start] = ThisParam(start, self.cls_name) self.lparams.append(start) start += 1 num_param = 0 for ptype in self.params_type: param = start + num_param self.lparams.append(param) self.var_to_name[param] = Param(param, ptype) num_param += util.get_type_size(ptype) if not __debug__: from androguard.core import bytecode # TODO: use tempfile to create a correct tempfile (cross platform compatible) bytecode.method2png('/tmp/dad/graphs/{}#{}.png'.format(self.cls_name.split('/')[-1][:-1], self.name), methanalysis) def process(self, doAST=False): logger.debug('METHOD : %s', self.name) # Native methods... no blocks. if self.start_block is None: logger.debug('Native Method.') if doAST: self.ast = JSONWriter(None, self).get_ast() else: self.writer = Writer(None, self) self.writer.write_method() return # Construct the CFG graph = construct(self.start_block, self.var_to_name, self.exceptions) self.graph = graph if not __debug__: # TODO: use tempfile to create a correct tempfile (cross platform compatible) util.create_png(self.cls_name, self.name, graph, '/tmp/dad/blocks') use_defs, def_uses = build_def_use(graph, self.lparams) split_variables(graph, self.var_to_name, def_uses, use_defs) dead_code_elimination(graph, def_uses, use_defs) register_propagation(graph, def_uses, use_defs) # FIXME var_to_name need to contain the created tmp variables. # This seems to be a workaround, we add them into the list manually for var, i in def_uses: if not isinstance(var, int): self.var_to_name[var] = var.upper() place_declarations(graph, self.var_to_name, def_uses, use_defs) del def_uses, use_defs # After the DCE pass, some nodes may be empty, so we can simplify the # graph to delete these nodes. # We start by restructuring the graph by spliting the conditional nodes # into a pre-header and a header part. split_if_nodes(graph) # We then simplify the graph by merging multiple statement nodes into # a single statement node when possible. This also delete empty nodes. simplify(graph) graph.compute_rpo() if not __debug__: # TODO: use tempfile to create a correct tempfile (cross platform compatible) util.create_png(self.cls_name, self.name, graph, '/tmp/dad/pre-structured') identify_structures(graph, graph.immediate_dominators()) if not __debug__: # TODO: use tempfile to create a correct tempfile (cross platform compatible) util.create_png(self.cls_name, self.name, graph, '/tmp/dad/structured') if doAST: self.ast = JSONWriter(graph, self).get_ast() else: self.writer = Writer(graph, self) self.writer.write_method() def get_ast(self): return self.ast def show_source(self): print(self.get_source()) def get_source(self): if self.writer: return str(self.writer) return '' def get_source_ext(self): if self.writer: return self.writer.str_ext() return [] def __repr__(self): # return 'Method %s' % self.name return 'class DvMethod(object): %s' % self.name
class DvMethod: """ This is a wrapper around :class:`~androguard.core.analysis.analysis.MethodAnalysis` and :class:`~androguard.core.bytecodes.dvm.EncodedMethod` inside the decompiler. """ def __init__(self, methanalysis): """ :param androguard.core.analysis.analysis.MethodAnalysis methanalysis: """ method = methanalysis.get_method() self.method = method self.start_block = next(methanalysis.get_basic_blocks().get(), None) self.cls_name = method.get_class_name() self.name = method.get_name() self.lparams = [] self.var_to_name = defaultdict() self.writer = None self.graph = None self.ast = None self.access = util.get_access_method(method.get_access_flags()) desc = method.get_descriptor() self.type = desc.split(')')[-1] self.params_type = util.get_params_type(desc) self.triple = method.get_triple() self.exceptions = methanalysis.exceptions.exceptions code = method.get_code() if code is None: logger.debug('No code : %s %s', self.name, self.cls_name) else: start = code.registers_size - code.ins_size if 'static' not in self.access: self.var_to_name[start] = ThisParam(start, self.cls_name) self.lparams.append(start) start += 1 num_param = 0 for ptype in self.params_type: param = start + num_param self.lparams.append(param) self.var_to_name[param] = Param(param, ptype) num_param += util.get_type_size(ptype) if not __debug__: from androguard.core import bytecode # TODO: use tempfile to create a correct tempfile (cross platform compatible) bytecode.method2png( '/tmp/dad/graphs/{}#{}.png'.format( self.cls_name.split('/')[-1][:-1], self.name), methanalysis) def process(self, doAST=False): logger.debug('METHOD : %s', self.name) # Native methods... no blocks. if self.start_block is None: logger.debug('Native Method.') if doAST: self.ast = JSONWriter(None, self).get_ast() else: self.writer = Writer(None, self) self.writer.write_method() return # Construct the CFG graph = construct(self.start_block, self.var_to_name, self.exceptions) self.graph = graph if not __debug__: # TODO: use tempfile to create a correct tempfile (cross platform compatible) util.create_png(self.cls_name, self.name, graph, '/tmp/dad/blocks') use_defs, def_uses = build_def_use(graph, self.lparams) split_variables(graph, self.var_to_name, def_uses, use_defs) dead_code_elimination(graph, def_uses, use_defs) register_propagation(graph, def_uses, use_defs) # FIXME var_to_name need to contain the created tmp variables. # This seems to be a workaround, we add them into the list manually for var, i in def_uses: if not isinstance(var, int): self.var_to_name[var] = var.upper() place_declarations(graph, self.var_to_name, def_uses, use_defs) del def_uses, use_defs # After the DCE pass, some nodes may be empty, so we can simplify the # graph to delete these nodes. # We start by restructuring the graph by spliting the conditional nodes # into a pre-header and a header part. split_if_nodes(graph) # We then simplify the graph by merging multiple statement nodes into # a single statement node when possible. This also delete empty nodes. simplify(graph) graph.compute_rpo() if not __debug__: # TODO: use tempfile to create a correct tempfile (cross platform compatible) util.create_png(self.cls_name, self.name, graph, '/tmp/dad/pre-structured') identify_structures(graph, graph.immediate_dominators()) if not __debug__: # TODO: use tempfile to create a correct tempfile (cross platform compatible) util.create_png(self.cls_name, self.name, graph, '/tmp/dad/structured') if doAST: self.ast = JSONWriter(graph, self).get_ast() else: self.writer = Writer(graph, self) self.writer.write_method() def get_ast(self): return self.ast def show_source(self): print(self.get_source()) def get_source(self): if self.writer: return str(self.writer) return '' def get_source_ext(self): if self.writer: return self.writer.str_ext() return [] def __repr__(self): # return 'Method %s' % self.name return 'class DvMethod(object): %s' % self.name
class DvMethod: """ This is a wrapper around :class:`~androguard.core.analysis.analysis.MethodAnalysis` and :class:`~androguard.core.bytecodes.dvm.EncodedMethod` inside the decompiler. :param androguard.core.analysis.analysis.MethodAnalysis methanalysis: """ def __init__(self, methanalysis, adi): method = methanalysis.get_method() self.method = method self.start_block = next(methanalysis.get_basic_blocks().get(), None) self.cls_name = method.get_class_name() self.name = method.get_name() self.lparams = [] self.var_to_name = defaultdict() self.adi = adi self.writer = None self.graph = None self.ast = None self.access = util.get_access_method(method.get_access_flags()) desc = method.get_descriptor() self.type = desc.split(')')[-1] self.params_type = util.get_params_type(desc) self.triple = method.get_triple() self.exceptions = methanalysis.exceptions.exceptions code = method.get_code() if code is None: logger.debug('No code : %s %s', self.name, self.cls_name) else: start = code.registers_size - code.ins_size if 'static' not in self.access: self.var_to_name[start] = ThisParam(start, self.cls_name) self.lparams.append(start) start += 1 num_param = 0 for ptype in self.params_type: param = start + num_param self.lparams.append(param) self.var_to_name[param] = Param(param, ptype) num_param += util.get_type_size(ptype) if self.adi != None: method_idx = method.get_method_idx() method_annotations = [ x.get_annotations_off() for x in self.adi.get_method_annotations() if x.get_method_idx() == method_idx ] param_annotations = [ x for x in self.adi.get_parameter_annotations() if x.get_method_idx() == method_idx ] self.method_annotations = get_annotations(method.CM, method_annotations) if len(param_annotations) > 0: self.param_annotations = get_parameter_annotations( method.CM, param_annotations) if len(self.param_annotations) != len(self.params_type): if len(self.params_type) - len( self.param_annotations) == 1: self.param_annotations.insert(0, []) else: print( "Failed to extract annotation from {} - {}".format( self.cls_name, self.name)) self.param_annotations = [[]] * len(self.params_type) else: self.param_annotations = [[]] * len(self.params_type) else: self.method_annotations = [] self.param_annotations = [[]] * len(self.params_type) if not __debug__: from androguard.core import bytecode # TODO: use tempfile to create a correct tempfile (cross platform compatible) bytecode.method2png( '/tmp/dad/graphs/{}#{}.png'.format( self.cls_name.split('/')[-1][:-1], self.name), methanalysis) def process(self, doAST=False): """ Processes the method and decompile the code. There are two modes of operation: 1) Normal Decompilation to Java Code 2) Decompilation into an abstract syntax tree (AST) The Decompilation is done twice. First, a rough decompilation is created, which is then optimized. Second, the optimized version is used to create the final version. :param doAST: generate AST instead of Java Code """ logger.debug('METHOD : %s', self.name) # Native methods... no blocks. if self.start_block is None: logger.debug('Native Method.') if doAST: self.ast = JSONWriter(None, self).get_ast() else: self.writer = Writer(None, self) self.writer.write_method() return # Construct the CFG graph = construct(self.start_block, self.var_to_name, self.exceptions) self.graph = graph if not __debug__: # TODO: use tempfile to create a correct tempfile (cross platform compatible) util.create_png(self.cls_name, self.name, graph, '/tmp/dad/blocks') use_defs, def_uses = build_def_use(graph, self.lparams) split_variables(graph, self.var_to_name, def_uses, use_defs) dead_code_elimination(graph, def_uses, use_defs) register_propagation(graph, def_uses, use_defs) resolve_variables_type(graph, self.var_to_name, def_uses, use_defs) new_instance_propgation(graph, def_uses, use_defs) #for dummy setattr(graph, "group_var", group_variables(self.var_to_name, def_uses, use_defs)) # FIXME var_to_name need to contain the created tmp variables. # This seems to be a workaround, we add them into the list manually for var, i in def_uses: if not isinstance(var, int): self.var_to_name[var] = var.upper() place_declarations(graph, self.var_to_name, def_uses, use_defs) del def_uses, use_defs # After the DCE pass, some nodes may be empty, so we can simplify the # graph to delete these nodes. # We start by restructuring the graph by spliting the conditional nodes # into a pre-header and a header part. split_if_nodes(graph) # We then simplify the graph by merging multiple statement nodes into # a single statement node when possible. This also delete empty nodes. simplify(graph) graph.compute_rpo() if not __debug__: # TODO: use tempfile to create a correct tempfile (cross platform compatible) util.create_png(self.cls_name, self.name, graph, '/tmp/dad/pre-structured') identify_structures(graph, graph.immediate_dominators()) if not __debug__: # TODO: use tempfile to create a correct tempfile (cross platform compatible) util.create_png(self.cls_name, self.name, graph, '/tmp/dad/structured') if doAST: self.ast = JSONWriter(graph, self).get_ast() else: self.writer = Writer(graph, self) self.writer.write_method() def get_ast(self): """ Returns the AST, if previously was generated by calling :meth:`process` with argument :code:`doAST=True`. The AST is a :class:`dict` with the following keys: * triple * flags * ret * params * comments * body The actual AST for the method is in the :code:`body`. :return: dict """ return self.ast def show_source(self): print(self.get_source()) def get_source(self): if self.writer: return str(self.writer) return '' def get_source_ext(self): if self.writer: return self.writer.str_ext() return [] def __repr__(self): # return 'Method %s' % self.name return '<class DvMethod(object): %s>' % self.name