def dex_2_smali(app_dir, tools_dir): """Run dex2smali.""" try: logger.info('DEX -> SMALI') dexes = get_dex_files(app_dir) for dex_path in dexes: logger.info('Converting %s to Smali Code', filename_from_path(dex_path)) if (len(settings.BACKSMALI_BINARY) > 0 and is_file_exists(settings.BACKSMALI_BINARY)): bs_path = settings.BACKSMALI_BINARY else: bs_path = os.path.join(tools_dir, 'baksmali-2.3.4.jar') output = os.path.join(app_dir, 'smali_source/') smali = [ settings.JAVA_BINARY, '-jar', bs_path, 'd', dex_path, '-o', output, ] trd = threading.Thread(target=subprocess.call, args=(smali, )) trd.daemon = True trd.start() except Exception: logger.exception('Converting DEX to SMALI')
def code_analysis(app_dir, typ): """Perform the code analysis.""" try: logger.info('Static Android Code Analysis Started') root = Path(settings.BASE_DIR) / 'StaticAnalyzer' / 'views' code_rules = root / 'android' / 'rules' / 'android_rules.yaml' api_rules = root / 'android' / 'rules' / 'android_apis.yaml' code_findings = {} api_findings = {} email_n_file = [] url_n_file = [] url_list = [] app_dir = Path(app_dir) if typ == 'apk': src = app_dir / 'java_source' elif typ == 'studio': src = app_dir / 'app' / 'src' / 'main' / 'java' kt = app_dir / 'app' / 'src' / 'main' / 'kotlin' if not src.exists() and kt.exists(): src = kt elif typ == 'eclipse': src = app_dir / 'src' src = src.as_posix() + '/' logger.info('Code Analysis Started on - %s', filename_from_path(src)) # Code and API Analysis code_findings = scan(code_rules.as_posix(), {'.java', '.kt'}, [src], settings.SKIP_CLASS_PATH) api_findings = scan(api_rules.as_posix(), {'.java', '.kt'}, [src], settings.SKIP_CLASS_PATH) skp = settings.SKIP_CLASS_PATH # Extract URLs and Emails for pfile in Path(src).rglob('*'): if ((pfile.suffix in ('.java', '.kt') and any(skip_path in pfile.as_posix() for skip_path in skp) is False)): content = None try: content = pfile.read_text('utf-8', 'ignore') # Certain file path cannot be read in windows except Exception: continue relative_java_path = pfile.as_posix().replace(src, '') urls, urls_nf, emails_nf = url_n_email_extract( content, relative_java_path) url_list.extend(urls) url_n_file.extend(urls_nf) email_n_file.extend(emails_nf) logger.info('Finished Code Analysis, Email and URL Extraction') code_an_dic = { 'api': api_findings, 'findings': code_findings, 'urls_list': url_list, 'urls': url_n_file, 'emails': email_n_file, } return code_an_dic except Exception: logger.exception('Performing Code Analysis')
def apkid_analysis(app_dir, apk_file, apk_name): """APKiD Analysis of DEX files""" apkid_res = {} if not settings.APKID_ENABLED: return apkid_res if not os.path.exists(apk_file): logger.error("APKiD - APK not found") return {'error': True} dest_dir = os.path.join(app_dir, "apkid") file_name = filename_from_path(apk_file) report_file = file_name + "_apkid.json" report = os.path.join(dest_dir, report_file) temporary_apk = os.path.join(dest_dir, file_name) if os.path.exists(dest_dir): shutil.rmtree(dest_dir) os.mkdir(dest_dir) shutil.copy2(apk_file, dest_dir) from apkid import apkid from apkid import __version__ as apkid_ver logger.info("Running APKiD %s on: %s", apkid_ver, file_name) result = apkid.scan(dest_dir, 30, True, dest_dir, True) with open(report, 'r') as f: result = json.load(f) for filep, res in result.items(): try: dex_file = filep.rsplit("!", 1)[1] except Exception: #dex_file = filename_from_path(filep) dex_file = apk_name apkid_res[dex_file] = res shutil.rmtree(dest_dir) return apkid_res
def apkid_analysis(app_dir, apk_file, apk_name): """APKiD Analysis of DEX files""" apkid_res = {} if not settings.APKID_ENABLED: return apkid_res if not os.path.exists(apk_file): logger.error("APKiD - APK not found") return {'error': True} dest_dir = os.path.join(app_dir, "apkid") file_name = filename_from_path(apk_file) report_file = file_name + "_apkid.json" report = os.path.join(dest_dir, report_file) temporary_apk = os.path.join(dest_dir, file_name) if os.path.exists(dest_dir): shutil.rmtree(dest_dir) os.mkdir(dest_dir) shutil.copy2(apk_file, dest_dir) from apkid import apkid from apkid import __version__ as apkid_ver logger.info("Running APKiD %s on: %s", apkid_ver, file_name) result = apkid.scan(dest_dir, 30, True, dest_dir, True) with open(report, 'r') as f: result = json.load(f) for filep, res in result.items(): try: dex_file = filep.rsplit("!", 1)[1] except Exception: #dex_file = filename_from_path(filep) dex_file = apk_name apkid_res[dex_file] = res shutil.rmtree(dest_dir) return apkid_res
def dex_2_jar(app_path, app_dir, tools_dir): """Run dex2jar.""" try: logger.info("DEX -> JAR") working_dir = None args = [] if settings.JAR_CONVERTER == "d2j": logger.info("Using JAR converter - dex2jar") dexes = get_dex_files(app_dir) for idx, dex in enumerate(dexes): logger.info("Converting " + filename_from_path(dex) + " to JAR") if len(settings.DEX2JAR_BINARY) > 0 and isFileExists( settings.DEX2JAR_BINARY): d2j = settings.DEX2JAR_BINARY else: if platform.system() == "Windows": win_fix_java(tools_dir) d2j = os.path.join(tools_dir, 'd2j2/d2j-dex2jar.bat') else: inv = os.path.join(tools_dir, 'd2j2/d2j_invoke.sh') d2j = os.path.join(tools_dir, 'd2j2/d2j-dex2jar.sh') subprocess.call(["chmod", "777", d2j]) subprocess.call(["chmod", "777", inv]) args = [ d2j, dex, '-f', '-o', app_dir + 'classes' + str(idx) + '.jar' ] subprocess.call(args) elif settings.JAR_CONVERTER == "enjarify": logger.info("Using JAR converter - Google enjarify") if len(settings.ENJARIFY_DIRECTORY) > 0 and isDirExists( settings.ENJARIFY_DIRECTORY): working_dir = settings.ENJARIFY_DIRECTORY else: working_dir = os.path.join(tools_dir, 'enjarify/') if platform.system() == "Windows": win_fix_python3(tools_dir) enjarify = os.path.join(working_dir, 'enjarify.bat') args = [ enjarify, app_path, "-f", "-o", app_dir + 'classes.jar' ] else: if len(settings.PYTHON3_PATH) > 2: python3 = os.path.join(settings.PYTHON3_PATH, "python3") else: python3 = get_python() args = [ python3, "-O", "-m", "enjarify.main", app_path, "-f", "-o", app_dir + 'classes.jar' ] subprocess.call(args, cwd=working_dir) except: PrintException("Converting Dex to JAR")
def jar_2_java(app_dir, tools_dir): """Conver jar to java.""" try: logger.info('JAR -> JAVA') jar_files = get_jar_files(app_dir) output = os.path.join(app_dir, 'java_source/') for jar_path in jar_files: logger.info( 'Decompiling %s to Java Code', filename_from_path(jar_path)) if settings.DECOMPILER == 'jd-core': ext_jdcore = settings.JD_CORE_DECOMPILER_BINARY if (len(ext_jdcore) > 0 and is_file_exists(ext_jdcore)): jd_path = ext_jdcore else: jd_path = os.path.join(tools_dir, 'jd-core.jar') args = [settings.JAVA_BINARY, '-jar', jd_path, jar_path, output] elif settings.DECOMPILER == 'cfr': ext_cfr = settings.CFR_DECOMPILER_BINARY if (len(ext_cfr) > 0 and is_file_exists(ext_cfr)): jd_path = ext_cfr else: jd_path = os.path.join(tools_dir, 'cfr-0.144.jar') args = [settings.JAVA_BINARY, '-jar', jd_path, jar_path, '--outputdir', output, '--silent', 'true'] elif settings.DECOMPILER == 'procyon': ext_proc = settings.PROCYON_DECOMPILER_BINARY if (len(ext_proc) > 0 and is_file_exists(ext_proc)): pd_path = ext_proc else: pd_path = os.path.join( tools_dir, 'procyon-decompiler-0.5.34.jar') args = [settings.JAVA_BINARY, '-jar', pd_path, jar_path, '-o', output] subprocess.call(args) except Exception: logger.exception('Converting JAR to JAVA')
def apkid_analysis(app_dir, apk_file): """APKiD Analysis of DEX files""" apkid_res = {} if not settings.APKID_ENABLED: return apkid_res if not os.path.exists(apk_file): logger.error("APKiD - APK not found") return {'error': True} from apkid import apkid from apkid import __version__ as apkid_ver logger.info("Running APKiD %s on: %s", apkid_ver, filename_from_path(apk_file)) result = apkid.scan_apk(apk_file, 30, True) for filep, res in result.items(): dex_file = filep.rsplit("!", 1)[1] apkid_res[dex_file] = res return apkid_res
def jar_2_java(app_dir, tools_dir): """Conver jar to java.""" try: logger.info("JAR -> JAVA") jar_files = get_jar_files(app_dir) output = os.path.join(app_dir, 'java_source/') for jar_path in jar_files: logger.info("Decompiling {} to Java Code".format( filename_from_path(jar_path))) if settings.DECOMPILER == 'jd-core': if (len(settings.JD_CORE_DECOMPILER_BINARY) > 0 and isFileExists(settings.JD_CORE_DECOMPILER_BINARY)): jd_path = settings.JD_CORE_DECOMPILER_BINARY else: jd_path = os.path.join(tools_dir, 'jd-core.jar') args = [ settings.JAVA_PATH + 'java', '-jar', jd_path, jar_path, output ] elif settings.DECOMPILER == 'cfr': if (len(settings.CFR_DECOMPILER_BINARY) > 0 and isFileExists(settings.CFR_DECOMPILER_BINARY)): jd_path = settings.CFR_DECOMPILER_BINARY else: jd_path = os.path.join(tools_dir, 'cfr-0.144.jar') args = [ settings.JAVA_PATH + 'java', '-jar', jd_path, jar_path, '--outputdir', output, '--silent', 'true' ] elif settings.DECOMPILER == "procyon": if (len(settings.PROCYON_DECOMPILER_BINARY) > 0 and isFileExists(settings.PROCYON_DECOMPILER_BINARY)): pd_path = settings.PROCYON_DECOMPILER_BINARY else: pd_path = os.path.join(tools_dir, 'procyon-decompiler-0.5.34.jar') args = [ settings.JAVA_PATH + 'java', '-jar', pd_path, jar_path, '-o', output ] subprocess.call(args) except: PrintException("Converting JAR to JAVA")
def dex_2_smali(app_dir, tools_dir): """Run dex2smali""" try: logger.info("DEX -> SMALI") dexes = get_dex_files(app_dir) for dex_path in dexes: logger.info("Converting " + filename_from_path(dex_path) + " to Smali Code") if len(settings.BACKSMALI_BINARY) > 0 and isFileExists(settings.BACKSMALI_BINARY): bs_path = settings.BACKSMALI_BINARY else: bs_path = os.path.join(tools_dir, 'baksmali-2.2.7.jar') output = os.path.join(app_dir, 'smali_source/') args = [ settings.JAVA_PATH + 'java', '-jar', bs_path, 'd', dex_path, '-o', output ] subprocess.call(args) except: PrintException("Converting DEX to SMALI")
def apkid_analysis(app_dir, apk_file, apk_name): """APKiD Analysis of DEX files""" apkid_res = {} if not settings.APKID_ENABLED: return apkid_res if not os.path.exists(apk_file): logger.error("APKiD - APK not found") return {'error': True} from apkid import __version__ as apkid_ver from apkid.apkid import Scanner, Options logger.info("Running APKiD") dest_dir = os.path.join(app_dir, "apkid") options = Options( timeout=30, verbose=None, json=True, output_dir=dest_dir, typing=None, entry_max_scan_size=100 * 1024 * 1024, scan_depth=2, recursive=True ) rules = options.rules_manager.load() scanner = Scanner(rules, options) scanner.scan(apk_file) file_name = filename_from_path(apk_file) report_file = file_name + "_apkid.json" report = os.path.join(dest_dir, report_file) with open(report, 'r') as flip: result = json.load(flip) for filep, res in result.items(): try: dex_file = filep.rsplit("!", 1)[1] except Exception: dex_file = apk_name apkid_res[dex_file] = res return apkid_res
def dex_2_jar(app_path, app_dir, tools_dir): """Run dex2jar.""" try: logger.info('DEX -> JAR') working_dir = None args = [] if settings.JAR_CONVERTER == 'd2j': logger.info('Using JAR converter - dex2jar') dexes = get_dex_files(app_dir) for idx, dex in enumerate(dexes): logger.info('Converting %s to JAR', filename_from_path(dex)) if (len(settings.DEX2JAR_BINARY) > 0 and is_file_exists(settings.DEX2JAR_BINARY)): d2j = settings.DEX2JAR_BINARY else: if platform.system() == 'Windows': win_fix_java(tools_dir) d2j = os.path.join(tools_dir, 'd2j2/d2j-dex2jar.bat') else: inv = os.path.join(tools_dir, 'd2j2/d2j_invoke.sh') d2j = os.path.join(tools_dir, 'd2j2/d2j-dex2jar.sh') os.chmod(d2j, 0o777) os.chmod(inv, 0o777) args = [ d2j, dex, '-f', '-o', app_dir + 'classes' + str(idx) + '.jar', ] subprocess.call(args) elif settings.JAR_CONVERTER == 'enjarify': logger.info('Using JAR converter - Google enjarify') if (len(settings.ENJARIFY_DIRECTORY) > 0 and is_dir_exists(settings.ENJARIFY_DIRECTORY)): working_dir = settings.ENJARIFY_DIRECTORY else: working_dir = os.path.join(tools_dir, 'enjarify/') if platform.system() == 'Windows': win_fix_python3(tools_dir) enjarify = os.path.join(working_dir, 'enjarify.bat') args = [ enjarify, app_path, '-f', '-o', app_dir + 'classes.jar' ] else: if len(settings.PYTHON3_PATH) > 2: python3 = os.path.join(settings.PYTHON3_PATH, 'python3') else: python3 = get_python() args = [ python3, '-O', '-m', 'enjarify.main', app_path, '-f', '-o', app_dir + 'classes.jar', ] subprocess.call(args, cwd=working_dir) except Exception: logger.exception('Converting Dex to JAR')
def code_analysis(app_dir, perms, typ): """Perform the code analysis.""" try: logger.info('Static Android Code Analysis Started') api_rules = android_apis.APIS code_rules = android_rules.RULES code_findings = {} api_findings = {} email_n_file = [] url_n_file = [] url_list = [] logger.info("code_findings-%s" % code_findings) if typ == 'apk': java_src = os.path.join(app_dir, 'java_source/') elif typ == 'studio': java_src = os.path.join(app_dir, 'app/src/main/java/') elif typ == 'eclipse': java_src = os.path.join(app_dir, 'src/') logger.info('Code Analysis Started on - %s', filename_from_path(java_src)) # pylint: disable=unused-variable # Needed by os.walk for dir_name, _sub_dir, files in os.walk(java_src): for jfile in files: jfile_path = os.path.join(java_src, dir_name, jfile) if '+' in jfile: p_2 = os.path.join(java_src, dir_name, jfile.replace('+', 'x')) shutil.move(jfile_path, p_2) jfile_path = p_2 repath = dir_name.replace(java_src, '') + '/' if (jfile.endswith('.java') and any( re.search(cls, repath) for cls in settings.SKIP_CLASSES) is False): dat = '' with io.open( jfile_path, mode='r', encoding='utf8', errors='ignore', ) as file_pointer: dat = file_pointer.read() # Code Analysis relative_java_path = jfile_path.replace(java_src, '') code_rule_matcher(code_findings, list(perms.keys()), dat, relative_java_path, code_rules) # API Check api_rule_matcher(api_findings, list(perms.keys()), dat, relative_java_path, api_rules) # Extract URLs and Emails urls, urls_nf, emails_nf = url_n_email_extract( dat, relative_java_path) url_list.extend(urls) url_n_file.extend(urls_nf) email_n_file.extend(emails_nf) logger.info('Finished Code Analysis, Email and URL Extraction') code_an_dic = { 'api': api_findings, 'findings': code_findings, 'urls_list': url_list, 'urls': url_n_file, 'emails': email_n_file, } return code_an_dic except Exception: logger.exception('Performing Code Analysis')
def code_analysis(app_dir, perms, typ): """Perform the code analysis.""" try: logger.info("Static Android Code Analysis Started") api_rules = android_apis.APIS code_rules = android_rules.RULES code_findings = {} api_findings = {} email_n_file = [] url_n_file = [] url_list = [] domains = {} if typ == "apk": java_src = os.path.join(app_dir, 'java_source/') elif typ == "studio": java_src = os.path.join(app_dir, 'app/src/main/java/') elif typ == "eclipse": java_src = os.path.join(app_dir, 'src/') logger.info("Code Analysis Started on - " + filename_from_path(java_src)) # pylint: disable=unused-variable # Needed by os.walk for dir_name, sub_dir, files in os.walk(java_src): for jfile in files: jfile_path = os.path.join(java_src, dir_name, jfile) if "+" in jfile: p_2 = os.path.join(java_src, dir_name, jfile.replace("+", "x")) shutil.move(jfile_path, p_2) jfile_path = p_2 repath = dir_name.replace(java_src, '') if (jfile.endswith('.java') and any( re.search(cls, repath) for cls in settings.SKIP_CLASSES) is False): dat = '' with io.open(jfile_path, mode='r', encoding="utf8", errors="ignore") as file_pointer: dat = file_pointer.read() # Code Analysis # print "[INFO] Doing Code Analysis on - " + jfile_path relative_java_path = jfile_path.replace(java_src, '') code_rule_matcher(code_findings, list(perms.keys()), dat, relative_java_path, code_rules) # API Check api_rule_matcher(api_findings, list(perms.keys()), dat, relative_java_path, api_rules) # Extract URLs and Emails urls, urls_nf, emails_nf = url_n_email_extract( dat, relative_java_path) url_list.extend(urls) url_n_file.extend(urls_nf) email_n_file.extend(emails_nf) # Domain Extraction and Malware Check logger.info("Performing Malware Check on extracted Domains") domains = malware_check(list(set(url_list))) logger.info("Finished Code Analysis, Email and URL Extraction") code_an_dic = { 'api': api_findings, 'findings': code_findings, 'urls': url_n_file, 'domains': domains, 'emails': email_n_file, } return code_an_dic except: PrintException("Performing Code Analysis")
def code_analysis(app_dir, perms, typ): """Perform the code analysis.""" try: logger.info("Static Android Code Analysis Started") api_rules = android_apis.APIS code_rules = android_rules.RULES code_findings = {} api_findings = {} email_n_file = [] url_n_file = [] url_list = [] domains = {} if typ == "apk": java_src = os.path.join(app_dir, 'java_source/') elif typ == "studio": java_src = os.path.join(app_dir, 'app/src/main/java/') elif typ == "eclipse": java_src = os.path.join(app_dir, 'src/') logger.info("Code Analysis Started on - " + filename_from_path(java_src)) # pylint: disable=unused-variable # Needed by os.walk for dir_name, sub_dir, files in os.walk(java_src): for jfile in files: jfile_path = os.path.join(java_src, dir_name, jfile) if "+" in jfile: p_2 = os.path.join(java_src, dir_name, jfile.replace("+", "x")) shutil.move(jfile_path, p_2) jfile_path = p_2 repath = dir_name.replace(java_src, '') if ( jfile.endswith('.java') and any(re.search(cls, repath) for cls in settings.SKIP_CLASSES) is False ): dat = '' with io.open( jfile_path, mode='r', encoding="utf8", errors="ignore" ) as file_pointer: dat = file_pointer.read() # Code Analysis # print "[INFO] Doing Code Analysis on - " + jfile_path relative_java_path = jfile_path.replace(java_src, '') code_rule_matcher( code_findings, list(perms.keys()), dat, relative_java_path, code_rules) # API Check api_rule_matcher(api_findings, list(perms.keys()), dat, relative_java_path, api_rules) # Extract URLs and Emails urls, urls_nf, emails_nf = url_n_email_extract(dat, relative_java_path) url_list.extend(urls) url_n_file.extend(urls_nf) email_n_file.extend(emails_nf) logger.info("Finished Code Analysis, Email and URL Extraction") code_an_dic = { 'api': api_findings, 'findings': code_findings, 'urls_list': url_list, 'urls': url_n_file, 'emails': email_n_file, } return code_an_dic except: PrintException("Performing Code Analysis")