def __init__(self, opener: str, closers: List[str], classname: str, reference_dx: Analysis = None, cg_filter: DiGraph = None): if reference_dx: self.classname = classname opener_analyses = reference_dx.find_methods(methodname=opener, classname=classname) self.openers = [x for x in opener_analyses] self.closers = [] for closer in closers: closer_gen = reference_dx.find_methods(methodname=closer, classname=classname) self.closers.extend([x for x in closer_gen]) # optionally filter out uninteresting openers based on # if they exist in a given call graph if cg_filter: self.openers = list( filter(lambda x: cg_filter.has_node(x.method), self.openers)) self.opener_path_generators = [] self.closer_path_generators = [] self.lifecycles = [] self.opener_paths = [] self.closer_paths = []
def get_apis(path): application = APK(path) application_dex = DalvikVMFormat(application.get_dex()) application_x = Analysis(application_dex) methods = set() cs = [cc.get_name() for cc in application_dex.get_classes()] for method in application_dex.get_methods(): g = application_x.get_method(method) if method.get_code() == None: continue for i in g.get_basic_blocks().get(): for ins in i.get_instructions(): output = ins.get_output() match = re.search(r'(L[^;]*;)->[^\(]*\([^\)]*\).*', output) if match and match.group(1) not in cs: methods.add(match.group()) methods = list(methods) return methods
def addAPK(self, filename, data): """ Add an APK file to the Session and run analysis on it. :param filename: (file)name of APK file :param data: binary data of the APK file :return: a tuple of SHA256 Checksum and APK Object """ digest = hashlib.sha256(data).hexdigest() log.debug("add APK:%s" % digest) apk = APK(data, True) self.analyzed_apk[digest] = [apk] self.analyzed_files[filename].append(digest) self.analyzed_digest[digest] = filename dx = Analysis() self.analyzed_vms[digest] = dx for dex in apk.get_all_dex(): # we throw away the output... FIXME? self.addDEX(filename, dex, dx, postpone_xref=True) # Postponed dx.create_xref() log.debug("added APK:%s" % digest) return digest, apk
def __analyse_ip__(self, a: apk.APK, dx: Analysis): print("analysing ip disclosure") # private address priv: [str] = [] privRe = re.compile(PRIVADDR) # ipv4 ipv4: [str] = [] rs: [StringAnalysis] = dx.find_strings(IPV4ADDR) for result in rs: result: StringAnalysis = result val = result.get_value() if privRe.match(val): priv.append(val) else: ipv4.append(val) self.ipv4 = ipv4 # ipv6 ipv6: [str] = [] rs: [StringAnalysis] = dx.find_strings(IPV6ADDR) for result in rs: result: StringAnalysis = result val = result.get_value() if privRe.match(val): priv.append(val) else: ipv6.append(val) self.ipv6 = ipv6 self.private_ip = priv pass
def addDEY(self, filename, data, dx=None): """ Add an ODEX file to the session and run the analysis """ digest = hashlib.sha256(data).hexdigest() log.debug("add DEY:%s" % digest) d = DalvikOdexVMFormat(data) log.debug("added DEY:%s" % digest) self.analyzed_files[filename].append(digest) self.analyzed_digest[digest] = filename self.analyzed_dex[digest] = d if self.export_ipython: d.create_python_export() if dx is None: dx = Analysis() dx.add(d) dx.create_xref() for d in dx.vms: # TODO: allow different decompiler here! d.set_decompiler(DecompilerDAD(d, dx)) d.set_vmanalysis(dx) self.analyzed_vms[digest] = dx return digest, d, dx
def find_method_used(self): """ funzione per ricercare i metodi che sono usati all'interno dell'apk, tanto lenta """ used_jadx = False if used_jadx: # Create DalvikVMFormat Object self.dalvik_format = DalvikVMFormat(self.apk) # Create Analysis Object self.analysis_object = Analysis(self.dalvik_format) # Load the decompiler # Make sure that the jadx executable is found in $PATH # or use the argument jadx="/path/to/jadx" to point to the executable decompiler = DecompilerJADX(self.dalvik_format, self.analysis_object) # propagate decompiler and analysis back to DalvikVMFormat self.dalvik_format.set_decompiler(decompiler) self.dalvik_format.set_vmanalysis(self.analysis_object) # Now you can do stuff like: list_method_analysis = self.analysis_object.get_methods() for method_analys in list_method_analysis: method_name = method_analys.get_method().get_name() # print(method_encoded.get_method().get_source()) self.method[method_name] = list(method_analys.get_xref_from()) elif self.use_analyze: # return apk, list dex , object analysis apk, self.dalvik_format, self.analysis_object = AnalyzeAPK( self.name_apk) for method_analys in self.analysis_object.get_methods(): method_name = method_analys.get_method().get_name() # from method_name get list dove esso viene chiamato self.method[method_name] = list(method_analys.get_xref_from()) elif self.use_smaliparser: # use smali parser, apktool and grep invece di Androguard dir_apk_tool = "temp_dir_" + self.name_only_apk + "/" list_method_to_analyze = self.conf["method_smali_parser"] self.method_2_value, self.all_url = smaliparser.start( dir_apk_tool, list_method_to_analyze) else: # TODO to make faster analysis but not work well self.dalvik_format = DalvikVMFormat(self.apk) for encoded_method in self.dalvik_format.get_methods(): method_analysis = MethodClassAnalysis(encoded_method) method_name = method_analysis.get_method().get_name() # print(method_name) # from method_name get list dove esso viene chiamato self.method[method_name] = list( method_analysis.get_xref_from())
class CFG(): def __init__(self, filename): self.filename = filename try: self.a = APK(filename) self.d = DalvikVMFormat(self.a.get_dex()) self.d.create_python_export() self.dx = Analysis(self.d) except zipfile.BadZipfile: # if file is not an APK, may be a dex object _, self.d, self.dx = AnalyzeDex(self.filename) self.d.set_vmanalysis(self.dx) self.dx.create_xref() self.cfg = self.build_cfg() def get_cg(self): return self.cfg def get_cfg(self): return self.dx.get_call_graph() def build_cfg(self): """ Using NX and Androguard, build a directed graph NX object so that: - node names are analysis.MethodClassAnalysis objects - each node has a label that encodes the method behavior """ cfg = self.get_cfg() ##/////////My changes/////////////// for n in cfg.nodes: instructions = [] # print(n) try: ops = n.get_instructions() for i in ops: instructions.append(i.get_name()) # print(ops) encoded_label = self.color_instructions(instructions) # print("No Exception") except AttributeError: encoded_label = np.array([0] * 15) cfg.node[n]["label"] = encoded_label return cfg def color_instructions(self, instructions): """ Node label based on coloring technique by Kruegel """ h = [0] * len(INSTRUCTION_CLASS_COLOR) for i in instructions: h[INSTRUCTION_SET_COLOR[i]] = 1 return np.array(h) def get_classes_from_label(self, label): classes = [ INSTRUCTION_CLASSES[i] for i in range(len(label)) if label[i] == 1 ] return classes
def __init__(self, filename): self.filename = filename try: self.a = APK(filename) self.d = DalvikVMFormat(self.a.get_dex()) self.d.create_python_export() self.dx = Analysis(self.d) except zipfile.BadZipfile: # if file is not an APK, may be a dex object _, self.d, self.dx = AnalyzeDex(self.filename) self.d.set_vmanalysis(self.dx) self.dx.create_xref() self.fcg = self.build_fcg()
def AnalyzeAPK(_file, session=None, raw=False): """ Analyze an android application and setup all stuff for a more quickly analysis! If session is None, no session is used at all. This is the default behaviour. If you like to continue your work later, it might be a good idea to use a session. A default session can be created by using :meth:`~get_default_session`. :param _file: the filename of the android application or a buffer which represents the application :type _file: string (for filename) or bytes (for raw) :param session: A session (default: None) :param raw: boolean if raw bytes are supplied instead of a filename :rtype: return the :class:`~androguard.core.bytecodes.apk.APK`, list of :class:`~androguard.core.bytecodes.dvm.DalvikVMFormat`, and :class:`~androguard.core.analysis.analysis.Analysis` objects """ log.debug("AnalyzeAPK") if session: log.debug("Using existing session {}".format(session)) if raw: data = _file filename = hashlib.md5(_file).hexdigest() else: with open(_file, "rb") as fd: data = fd.read() filename = _file digest = session.add(filename, data) return session.get_objects_apk(filename, digest) else: log.debug("Analysing without session") a = APK(_file, raw=raw) # FIXME: probably it is not necessary to keep all DalvikVMFormats, as # they are already part of Analysis. But when using sessions, it works # this way... d = [] dx = Analysis() for dex in a.get_all_dex(): df = DalvikVMFormat(dex, using_api=a.get_target_sdk_version()) dx.add(df) d.append(df) df.set_decompiler(decompiler.DecompilerDAD(d, dx)) dx.create_xref() return a, d, dx
def link_callbacks(mca: MethodClassAnalysis, dx: Analysis, ast: Dict, cg: nx.DiGraph): android_api_callbacks = get_cb_methods() invoked_callback_registers = get_callback_list(mca, dx, ast, android_callback_interfaces) def is_android_api_callback(callback_tuple): _, interface = callback_tuple if interface in android_api_callbacks: return True return False invoked_callback_registers = filter(is_android_api_callback, invoked_callback_registers) found_methods = list() for cb_typ, cb_interface in invoked_callback_registers: java_interface: JavaInterface = android_api_callbacks[cb_interface] interface_method: JavaMethod # Try to find the analysis for the interface methods. # This should be successful if an interface method is # used by any user code, but I'll need to verify edge cases. for interface_method in java_interface.methods: gen = dx.find_methods( classname=cb_typ, methodname=".*{}.*".format(interface_method.name) ) analysis: MethodClassAnalysis found = False for item in gen: analysis = item found = True if found: found_methods.append(analysis.method) for method_enc in found_methods: print("adding edge: ", mca.name, " -> ", method_enc.name) cg.add_edge(mca.method, method_enc)
def __analyse_sql__(self, a: apk.APK, dx: Analysis): print("analysing sqlite") # raw query methods = dx.find_methods("Landroid/database/sqlite/.*", "execSQL|rawQuery") raw_query_injects: [(ClassAnalysis, EncodedMethod)] = [] # cipher key hardcoded encrypts: [(ClassAnalysis, EncodedMethod)] = [] # check whether variables/user inputs are involved in SQL statements (filter out constant values) for m in methods: # raw_query_injects.append(m) # 1. should implement code tracing variables # 2. find encryption entry. Hint: db.execSQL("PRAGMA key = 'secretkey'"); m: MethodClassAnalysis = m p_list: [(ClassAnalysis, object, int)] = m.get_xref_from() for (p_class, p_method, _) in p_list: if type(p_method) is ExternalMethod: continue p_method: EncodedMethod = p_method item = (p_class, p_method) if "PRAGMA key" in p_method.get_source(): if item not in encrypts: # may contain hardcoded keys encrypts.append(item) elif item not in raw_query_injects: # may leak raw_query_injects.append(item) break self.sql_raw_query_inject_methods = raw_query_injects self.sql_encrypt_secret_hardcoded_methods = encrypts pass
def __analyse_insecure_secure_random__(self, a: apk.APK, dx: Analysis): print("analysing insecure random") # find java.util.Random self.insecure_randoms: [(ClassAnalysis, EncodedMethod)] = [] methods = dx.find_methods("Ljava/util/Random|Lkotlin/random/Random", r"next\s*") for m in methods: # check its parent method to find wrong parameters m: MethodClassAnalysis = m p_list: [(ClassAnalysis, object, int)] = m.get_xref_from() for (p_class, p_method, _) in p_list: # find first parent method p_class: ClassAnalysis = p_class class_name: str = p_class.name # jump out of kotlin packages if p_method is ExternalMethod or class_name.startswith( 'Lkotlin'): continue item = (p_class, p_method) if item not in self.insecure_randoms: self.insecure_randoms.append(item) break pass
def __analyse_insecure_hash_function__(self, a: apk.APK, dx: Analysis): print("analysing insecure hash function") # find all md4, rc2, rc4, md5, sha-1 self.weak_hash: [(ClassAnalysis, EncodedMethod)] = [] # find general weak hash methods = dx.find_methods("Ljava/security/MessageDigest", "getInstance") reWeakHash = re.compile(r'md5|md4|rc2|sha-1', re.IGNORECASE) for m in methods: # check its parent method to find wrong parameters m: MethodClassAnalysis = m p_list: [(ClassAnalysis, object, int)] = m.get_xref_from() for (p_class, p_method, _) in p_list: if type(p_method) is not EncodedMethod: continue # iterate parent methods p_method: EncodedMethod = p_method # find wrong encryption options for ins in p_method.get_instructions(): ins: Instruction = ins if ins.get_name() != 'const-string': continue output = ins.get_output() item = (p_class, p_method) if reWeakHash.search(output): if item not in self.weak_hash: self.weak_hash.append(item) break methods = dx.find_methods( "Lorg/apache/commons/codec/digest/DigestUtils", "md5|sha") for m in methods: # check its parent method to find wrong parameters m: MethodClassAnalysis = m p_list: [(ClassAnalysis, object, int)] = m.get_xref_from() for (p_class, p_method, _) in p_list: if type(p_method) is not EncodedMethod: continue item = (p_class, p_method) if item not in self.weak_hash: self.weak_hash.append((p_class, p_method)) break pass
def extract_features(file_path): a = APK(file_path) d = DalvikVMFormat(a.get_dex()) dx = Analysis(d) vm = dvm.DalvikVMFormat(a.get_dex()) vmx = analysis.Analysis(vm) d.set_vmanalysis(dx) d.set_decompiler(DecompilerDAD(d, dx)) return a.get_permissions()
def __init__(self, filename): self.filename = filename # print(os.path.exists(filename)) # a,d,dx = AnalyzeAPK(filename) # print(dx.get_call_graph()) try: self.a = APK(filename) self.d = DalvikVMFormat(self.a.get_dex()) self.d.create_python_export() self.dx = Analysis(self.d) except zipfile.BadZipfile: # if file is not an APK, may be a dex object _, self.d, self.dx = AnalyzeDex(self.filename) self.d.set_vmanalysis(self.dx) self.dx.create_xref() self.fcg = self.build_fcg()
def run(self): unique_apis = [] for apk in self.apks_list: try: with ZipFile(apk) as zipfile: # find .dex files inside apk dexes = [dex for dex in zipfile.namelist() if dex.endswith('.dex')] dx = Analysis() # analyze every .dex for dex in dexes: with zipfile.open(dex) as dexfile: d = DalvikVMFormat(dexfile.read()) dx.add(d) # creates cross references between classes, methods, etc. for all the .dex dx.create_xref() # extracting android apis apis = self.get_api_calls(dx) not_unique = unique_apis + apis unique_apis = list(np.unique(not_unique)) print('Process %d: %.1f%%' % (self.process_id, ((self.apks_list.index(apk) + 1) / self.total_apks) * 100)) except BadZipfile as e: print('Bad zip file =========> %s' % apk) except Exception as e: print('\n%s\n%s\n' % (apk, e)) self.queue.put(unique_apis) print('----------------> Process %d is done!' % self.process_id)
def addDEX(self, filename, data, dx=None): """ Add a DEX file to the Session and run analysis. :param filename: the (file)name of the DEX file :param data: binary data of the dex file :param dx: an existing Analysis Object (optional) :return: A tuple of SHA256 Hash, DalvikVMFormat Object and Analysis object """ digest = hashlib.sha256(data).hexdigest() log.debug("add DEX:%s" % digest) log.debug("Parsing format ...") d = DalvikVMFormat(data) log.debug("added DEX:%s" % digest) self.analyzed_files[filename].append(digest) self.analyzed_digest[digest] = filename self.analyzed_dex[digest] = d if dx is None: dx = Analysis() dx.add(d) dx.create_xref() # TODO: If multidex: this will called many times per dex, even if already set for d in dx.vms: # TODO: allow different decompiler here! d.set_decompiler(DecompilerDAD(d, dx)) d.set_vmanalysis(dx) self.analyzed_vms[digest] = dx if self.export_ipython: log.debug("Exporting in ipython") d.create_python_export() return digest, d, dx
def extract_features(file_path): #result = [] try: a = APK(file_path) d = DalvikVMFormat(a.get_dex()) dx = Analysis(d) vm = dvm.DalvikVMFormat(a.get_dex()) vmx = analysis.uAnalysis(vm) d.set_Analysis(dx) d.set_decompiler(DecompilerDAD(d, dx)) except: return None return a.get_permissions() #it will return permission
def __detect_su_detection__(self, dx: Analysis): print("analysing su detection") self.su_detections: [(ClassAnalysis, EncodedMethod)] = [] # find methods that contains these su paths rs: [StringAnalysis] = dx.find_strings(r"/system/app/Superuser.apk|/system/bin/failsafe/su|/system/sd/xbin/su") for result in rs: result: StringAnalysis = result p_list: [(ClassAnalysis, object)] = result.get_xref_from() # find direct parent method who trigger this method for (p_class, p_method) in p_list: if type(p_method) is not EncodedMethod: continue item = (p_class, p_method) if item not in self.su_detections: self.su_detections.append(item) break # RootTools or Root detection rss: [MethodClassAnalysis] = dx.find_methods("Lcom/stericson/RootTools/RootTools|Ldexguard/util/RootDetector", "isAccessGiven|isDeviceRooted") for rst in rss: rst: MethodClassAnalysis = rst p_list: [(ClassAnalysis, object, int)] = rst.get_xref_from() # find direct parent method who trigger this method for (p_class, p_method, _) in p_list: if type(p_method) is not EncodedMethod: continue item = (p_class, p_method) if item not in self.su_detections: self.su_detections.append(item) break pass
def __detect_debug__(self, dx: Analysis): print("analysing debugging detection") self.debug_detections: [(ClassAnalysis, EncodedMethod)] = [] rss: [MethodClassAnalysis] = dx.find_methods("Ldexguard/util/.*", "isDebuggable|isDebuggerConnected|isRunningInEmulator|isSignedWithDebugKey") for rst in rss: rst: MethodClassAnalysis = rst p_list: [(ClassAnalysis, object, int)] = rst.get_xref_from() # find direct parent method who trigger this method for (p_class, p_method, _) in p_list: if type(p_method) is not EncodedMethod: continue item = (p_class, p_method) if item not in self.su_detections: self.debug_detections.append(item) break pass
def __analyse_insecure_webview_implementation(self, dx: Analysis): print("analysing insecure webview implementation") methods = dx.find_methods("Landroid/webkit/WebViewClient", "onReceivedSslError") self.webview_insecure_implementation: [(ClassAnalysis, EncodedMethod) ] = [] for m in methods: # check its parent method to find wrong parameters m: MethodClassAnalysis = m p_list: [(ClassAnalysis, object, int)] = m.get_xref_from() for (p_class, p_method, _) in p_list: if type(p_method) is not EncodedMethod: continue item = (p_class, p_method) if item not in self.webview_insecure_implementation: self.webview_insecure_implementation.append(item) break pass
def __analyse_insecure_certificate_validation__(self, dx: Analysis): print("analysing insecure certificate validation") methods = dx.find_methods("Ljavax/net/ssl/.*", "setDefaultHostnameVerifier") self.insecure_certificate_validation: [(ClassAnalysis, EncodedMethod) ] = [] for m in methods: # check its parent method to find wrong parameters m: MethodClassAnalysis = m p_list: [(ClassAnalysis, object, int)] = m.get_xref_from() for (p_class, p_method, _) in p_list: if type(p_method) is not EncodedMethod: continue item = (p_class, p_method) if item not in self.insecure_certificate_validation: self.insecure_certificate_validation.append(item) break pass
def __analyse_improper_encryption__(self, a: apk.APK, dx: Analysis): print("analysing improper encryption") # check improper encryption self.encryption_vuln_ecb: [(ClassAnalysis, EncodedMethod)] = [] self.encryption_vuln_rsa_no_oaep: [(ClassAnalysis, EncodedMethod)] = [] methods = dx.find_methods("Ljavax/crypto/Cipher", "getInstance") reECB = re.compile( r'AES/ECB', re.IGNORECASE ) # The App uses ECB mode in Cryptographic encryption algorithm. reRsaNoPadding = re.compile( r'rsa/.+/nopadding', re.IGNORECASE) # This App uses RSA Crypto without OAEP padding. for m in methods: # check its parent method to find wrong parameters m: MethodClassAnalysis = m p_list: [(ClassAnalysis, object, int)] = m.get_xref_from() for (p_class, p_method, _) in p_list: if type(p_method) is not EncodedMethod: continue # iterate parent methods p_method: EncodedMethod = p_method # find wrong encryption options for ins in p_method.get_instructions(): ins: Instruction = ins if ins.get_name() != 'const-string': continue output = ins.get_output() item = (p_class, p_method) if reECB.search(output): if item not in self.encryption_vuln_ecb: self.encryption_vuln_ecb.append(item) break elif reRsaNoPadding.search(output): if item not in self.encryption_vuln_rsa_no_oaep: self.encryption_vuln_rsa_no_oaep.append(item) break pass
def __detect_su_usage__(self, dx: Analysis): print("analysing root usage") # find out su root usage self.su_usages: [(ClassAnalysis, EncodedMethod)] = [] # su packages rss: [MethodClassAnalysis] = dx.find_methods( "Lcom/noshufou/android/su/.*|Lcom/thirdparty/superuser/.*|Leu/chainfire/.*|Lcom/koushikdutta/superuser/.*") for rst in rss: rst: MethodClassAnalysis = rst p_list: [(ClassAnalysis, object, int)] = rst.get_xref_from() # find direct parent method who trigger this method for (p_class, p_method, _) in p_list: if type(p_method) is not EncodedMethod: continue item = (p_class, p_method) if item not in self.su_usages: self.su_usages.append(item) break pass
def __analyse_storage__(self, dx: Analysis): print("analysing storage issues") self.storage_issues: [(ClassAnalysis, EncodedMethod)] = [] # storage rss = dx.find_methods( "Landroid/os/Environment|Ljava/io/File|Landroid/content/Context", r"getExternalStorage*|getExternalFilesDir|createTempFile|openFileOutput" ) for m in rss: m: MethodClassAnalysis = m p_list: [(ClassAnalysis, object, int)] = m.get_xref_from() for (p_class, p_method, _) in p_list: if type(p_method) is not EncodedMethod: continue # iterate parent methodsO item = (p_class, p_method) if item not in self.storage_issues: self.storage_issues.append(item) break
def parse_dx(dx: Analysis, fn_match=None, outfile=None): console = Console() out = {} out.update(JNI_COMMON) count = 0 for cx in dx.get_internal_classes(): methods = parse_class_def(cx.get_class()) count += 1 if not methods: continue cname = methods[0].jclass if fn_match and not fn_match(cname): continue for m in methods: out.update(m.as_dict) console.log(f"Parse {count} classes.") console.log(f"Found {len(out)} JNI methods.") if not outfile: console.print_json(data=out) else: with open(outfile, 'w') as f: json.dump(out, f, indent=2, ensure_ascii=False)
def __analyse_remote_webview_debugging__(self, a: apk.APK, dx: Analysis): print("analysing webview debugging options") # find WebView debug function methods = dx.find_methods("Landroid/webkit/WebView", "setWebContentsDebuggingEnabled") self.webview_debugs: [(ClassAnalysis, EncodedMethod)] = [] for m in methods: # check its parent method to find wrong parameters m: MethodClassAnalysis = m p_list: [(ClassAnalysis, object, int)] = m.get_xref_from() for (p_class, p_method, _) in p_list: if type(p_method) is not EncodedMethod: continue # iterate parent methods p_method: EncodedMethod = p_method # find wrong encryption options code: str = p_method.get_source() item = (p_class, p_method) if "setWebContentsDebuggingEnabled(1)" in code: if item not in self.webview_debugs: self.webview_debugs.append(item) break pass
def __analyse_trackers__(self, a: apk.APK, dx: Analysis): print("analysing trackers") self.trackers: [{str: str}] = [] # [{name : website}] # load trackers. We use exodus tracker list: https://etip.exodus-privacy.eu.org/trackers/all with open( os.path.join(os.path.dirname(__file__), "assets" + os.path.sep + 'trackers.json'), 'r') as file: json_obj = json.load(file) trackers = json_obj['trackers'] # check the code signature for item in trackers: name = item['name'] website = item['website'] code_signature: str = item['code_signature'] code_signature = "L" + code_signature.replace('.', '/') if code_signature[-1] != '/': code_signature = code_signature + '/' code_signature = code_signature + '.*' # make the code signature as Lcom/example/.* results = dx.find_classes(code_signature, True) for _ in results: # contains such tracker self.trackers.append({name: website}) break
def get_callback_list(mca: MethodClassAnalysis, dx: Analysis, ast: Dict, callback_interfaces: List): classname: str = mca.method.class_name methodname: str = mca.name method_ast = get_method_from_ast(methodname, classname, ast) if method_ast: method_ast_body = method_ast['body'] else: return [] method_invocs = get_method_invocations(method_ast_body) registered_callbacks = [] for invoc in method_invocs: arg_types = get_method_arg_type(invoc) for typ in arg_types: cls: ClassAnalysis = dx.get_class_analysis(typ) if isinstance(cls, ClassAnalysis): for interface in cls.implements: if interface in callback_interfaces: print( "Found registered resource: ", typ, "implements ", interface ) registered_callbacks.append((typ, interface)) return registered_callbacks
def addDEX(self, filename, data, dx=None, postpone_xref=False): """ Add a DEX file to the Session and run analysis. :param filename: the (file)name of the DEX file :param data: binary data of the dex file :param dx: an existing Analysis Object (optional) :param postpone_xref: True if no xref shall be created, and will be called manually :return: A tuple of SHA256 Hash, DalvikVMFormat Object and Analysis object """ digest = hashlib.sha256(data).hexdigest() log.debug("add DEX:%s" % digest) log.debug("Parsing format ...") d = DalvikVMFormat(data) log.debug("added DEX:%s" % digest) self.analyzed_files[filename].append(digest) self.analyzed_digest[digest] = filename self.analyzed_dex[digest] = d if dx is None: dx = Analysis() dx.add(d) if not postpone_xref: dx.create_xref() # TODO: If multidex: this will called many times per dex, even if already set for d in dx.vms: # TODO: allow different decompiler here! d.set_decompiler(DecompilerDAD(d, dx)) d.set_vmanalysis(dx) self.analyzed_vms[digest] = dx if self.export_ipython: log.debug("Exporting in ipython") d.create_python_export() return digest, d, dx
from androguard.core.bytecodes.apk import APK from androguard.core.bytecodes.dvm import DalvikVMFormat from androguard.core.analysis.analysis import Analysis from androguard.decompiler.decompiler import DecompilerJADX from androguard.core.androconf import show_logging import logging # Enable log output show_logging(level=logging.DEBUG) # Load our example APK a = APK("examples/android/TestsAndroguard/bin/TestActivity.apk") # Create DalvikVMFormat Object d = DalvikVMFormat(a) # Create Analysis Object dx = Analysis(d) # Load the decompiler # Set the path to the jadx executable! decompiler = DecompilerJADX(d, dx, jadx="/home/vagrant/jadx/build/jadx/bin/jadx") # propagate decompiler and analysis back to DalvikVMFormat d.set_decompiler(decompiler) d.set_vmanalysis(dx) # Now you can do stuff like: for m in d.get_methods()[:10]: print(m) print(decompiler.get_source_method(m))
def main(): for path in samples(): print(path) logging.error("Processing" + path) tests_apk = ["is_valid_APK", "get_filename", "get_app_name", "get_app_icon", "get_package", "get_androidversion_code", "get_androidversion_name", "get_files", "get_files_types", "get_files_crc32", "get_files_information", "get_raw", "get_dex", "get_all_dex", "get_main_activity", "get_activities", "get_services", "get_receivers", "get_providers", "get_permissions", "get_details_permissions", "get_requested_aosp_permissions", "get_requested_aosp_permissions_details", "get_requested_third_party_permissions", "get_declared_permissions", "get_declared_permissions_details", "get_max_sdk_version", "get_min_sdk_version", "get_target_sdk_version", "get_libraries", "get_android_manifest_axml", "get_android_manifest_xml", "get_android_resources", "get_signature_name", "get_signature_names", "get_signature", "get_signatures"] tests_dex = ["get_api_version", "get_classes_def_item", "get_methods_id_item", "get_fields_id_item", "get_codes_item", "get_string_data_item", "get_debug_info_item", "get_header_item", "get_class_manager", "show", "save", "get_classes_names", "get_classes", "get_all_fields", "get_fields", "get_methods", "get_len_methods", "get_strings", "get_format_type", "create_python_export", "get_BRANCH_DVM_OPCODES", "get_determineNext", "get_determineException", "print_classes_hierarchy", "list_classes_hierarchy", "get_format"] try: # Testing APK a = APK(path) for t in tests_apk: print(t) x = getattr(a, t) try: x() except Exception as aaa: print(aaa) traceback.print_exc() print(path, aaa, file=sys.stderr) logging.exception("{} .. {}".format(path, t)) # Testing DEX for dex in a.get_all_dex(): d = DalvikVMFormat(dex) dx = Analysis(d) d.set_vmanalysis(dx) # Test decompilation for c in d.get_classes(): for m in c.get_methods(): mx = dx.get_method(m) ms = DvMethod(mx) try: ms.process(doAST=True) except Exception as aaa: print(aaa) traceback.print_exc() print(path, aaa, file=sys.stderr) logging.exception("{} .. {} .. {}".format(path, c.get_name(), m.get_name())) ms2 = DvMethod(mx) try: ms2.process(doAST=False) except Exception as aaa: print(aaa) traceback.print_exc() print(path, aaa, file=sys.stderr) logging.exception("{} .. {} .. {}".format(path, c.get_name(), m.get_name())) # Other tests for t in tests_dex: print(t) x = getattr(d, t) try: x() except Exception as aaa: print(aaa) traceback.print_exc() print(path, aaa, file=sys.stderr) logging.exception("{} .. {}".format(path, t)) except KeyboardInterrupt: raise except FileNotFoundError: pass except Exception as e: print(e) traceback.print_exc() print(path, e, file=sys.stderr) logging.exception(path)