def apkid_analysis(sha256): es.update(index=settings.ELASTICSEARCH_TASKS_INDEX, id=sha256, body={'doc': { 'apkid_analysis': 1 }}, retry_on_conflict=5) options = Options( timeout=30, verbose=False, entry_max_scan_size=settings.DATA_UPLOAD_MAX_MEMORY_SIZE, recursive=True, ) output = OutputFormatter( json_output=True, output_dir=None, rules_manager=RulesManager(), include_types=False, ) rules = options.rules_manager.load() scanner = Scanner(rules, options) with NamedTemporaryFile() as f: f.write(default_storage.open(sha256).read()) f.seek(0) res = scanner.scan_file(f.name) try: findings = output.build_json_output(res)['files'] es.update(index=settings.ELASTICSEARCH_APK_INDEX, id=sha256, body={'doc': { 'apkid': findings }}, retry_on_conflict=5) es.update(index=settings.ELASTICSEARCH_TASKS_INDEX, id=sha256, body={'doc': { 'apkid_analysis': 2 }}, retry_on_conflict=5) except AttributeError: findings = {} es.update(index=settings.ELASTICSEARCH_APK_INDEX, id=sha256, body={'doc': { 'apkid': findings }}, retry_on_conflict=5) es.update(index=settings.ELASTICSEARCH_TASKS_INDEX, id=sha256, body={'doc': { 'apkid_analysis': -1 }}, retry_on_conflict=5) del findings, rules, scanner, output, options, res gc.collect() return {'status': 'success', 'info': ''}
def apkid_analysis(app_dir, apk_file, apk_name): """APKiD Analysis of DEX files""" if not settings.APKID_ENABLED: return {} if not os.path.exists(apk_file): logger.error("APKiD - APK not found") return {} from apkid import __version__ as apkid_ver from apkid.apkid import Scanner, Options from apkid.output import OutputFormatter from apkid.rules import RulesManager logger.info("Running APKiD %s", apkid_ver) options = Options(timeout=30, verbose=False, entry_max_scan_size=100 * 1024 * 1024, recursive=True) output = OutputFormatter(json_output=True, output_dir=None, rules_manager=RulesManager()) rules = options.rules_manager.load() scanner = Scanner(rules, options) res = scanner.scan_file(apk_file) findings = output._build_json_output(res)['files'] sanitized = {} for item in findings: filename = item['filename'] sanitized[filename] = item['matches'] return sanitized
def apkid_analysis(app_dir, apk_file, apk_name): """APKID Analysis of DEX files.""" if not settings.APKID_ENABLED: return {} try: import apkid except ImportError: logger.error('APKiD - Could not import APKiD') return {} if not os.path.exists(apk_file): logger.error('APKiD - APK not found') return {} apkid_ver = apkid.__version__ from apkid.apkid import Scanner, Options from apkid.output import OutputFormatter from apkid.rules import RulesManager logger.info('Running APKiD %s', apkid_ver) options = Options( timeout=30, verbose=False, entry_max_scan_size=settings.DATA_UPLOAD_MAX_MEMORY_SIZE, recursive=True, ) output = OutputFormatter( json_output=True, output_dir=None, rules_manager=RulesManager(), include_types=False, ) rules = options.rules_manager.load() scanner = Scanner(rules, options) res = scanner.scan_file(apk_file) try: findings = output._build_json_output(res)['files'] except AttributeError: # apkid >= 2.0.3 try: findings = output.build_json_output(res)['files'] except AttributeError: logger.error('yara-python dependency required by ' 'APKiD is not installed properly. ' 'Skipping APKiD analysis!') findings = {} sanitized = {} for item in findings: filename = item['filename'] if '!' in filename: filename = filename.split('!', 1)[1] sanitized[filename] = item['matches'] return sanitized
def main(): parser = get_parser() args = parser.parse_args() options = build_options(args) if not options.output.json: print(f"[+] APKiD {__version__} :: from RedNaga :: rednaga.io") rules = options.rules_manager.load() scanner = Scanner(rules, options) for input in args.input: scanner.scan(input)
def test_scan_with_nested_zips(scanner: Scanner): third_layer = {'3.dex': b'dex\n'} second_layer = { '3.zip': make_zip(third_layer).read(), '2.dex': b'dex\n', } first_layer = { '2.zip': make_zip(second_layer).read(), '1.dex': b'dex\n', } zero_layer = { '1.zip': make_zip(first_layer).read(), '0.dex': b'dex\n', } scanner.options.scan_depth = 2 with make_temp_zip(zero_layer) as tz: results = scanner.scan_file(tz.name) for key in (tz.name, f'{tz.name}!0.dex', f'{tz.name}!1.zip', f'{tz.name}!1.zip!1.dex', f'{tz.name}!1.zip!2.zip', f'{tz.name}!1.zip!2.zip!2.dex', f'{tz.name}!1.zip!2.zip!3.zip'): assert key in results assert len(results[key]) > 0
def test_scan_with_nested_zips(scanner: Scanner): third_layer = {'3.dex': b'dex\n'} second_layer = { '3.zip': make_zip(third_layer).read(), '2.dex': b'dex\n', } first_layer = { '2.zip': make_zip(second_layer).read(), '1.dex': b'dex\n', } zero_layer = { '1.zip': make_zip(first_layer).read(), '0.dex': b'dex\n', } print('zero layer', zero_layer) scanner.options.scan_depth = 2 with make_temp_zip(zero_layer) as tz: filename: str = os.path.basename(tz.name) results = scanner.scan_file(tz.name) print('all results', results) for key in (filename, f'{filename}!0.dex', f'{filename}!1.zip', f'{filename}!1.zip!1.dex', f'{filename}!1.zip!2.zip', f'{filename}!1.zip!2.zip!2.dex', f'{filename}!1.zip!2.zip!3.zip'): assert key in results assert len(results[key]) > 0
def test_scan_with_zip_with_dex(scanner: Scanner): zip_entries = {'classes.dex': b'dex\nnot a real dex!'} with make_temp_zip(zip_entries) as tz: results = scanner.scan_file(tz.name) for key in (tz.name, f'{tz.name}!classes.dex'): assert key in results assert len(results[key]) > 0
def test_scan_with_dummy_zip(scanner: Scanner): zip_entries = {'dummy': b'hello'} with make_temp_zip(zip_entries) as tz: results = scanner.scan_file(tz.name) assert tz.name in results assert len(results) == 1 assert len(results[tz.name]) > 0
def test_scan_with_dummy_zip(scanner: Scanner): zip_entries = {'dummy': b'hello'} with make_temp_zip(zip_entries) as tz: filename: str = os.path.basename(tz.name) results = scanner.scan_file(tz.name) assert filename in results assert len(results[filename]) > 0
def apkid_analysis(app_dir, apk_file, apk_name): """APKID Analysis of DEX files.""" if not settings.APKID_ENABLED: return {} try: import apkid except ImportError: logger.error('APKiD - Could not import APKiD') return {} if not os.path.exists(apk_file): logger.error('APKiD - APK not found') return {} apkid_ver = apkid.__version__ from apkid.apkid import Scanner, Options from apkid.output import OutputFormatter from apkid.rules import RulesManager logger.info('Running APKiD %s', apkid_ver) options = Options( timeout=30, verbose=False, entry_max_scan_size=100 * 1024 * 1024, recursive=True, ) output = OutputFormatter( json_output=True, output_dir=None, rules_manager=RulesManager(), include_types=False, ) rules = options.rules_manager.load() scanner = Scanner(rules, options) res = scanner.scan_file(apk_file) try: findings = output._build_json_output(res)['files'] except AttributeError: # apkid >= 2.0.3 findings = output.build_json_output(res)['files'] sanitized = {} for item in findings: filename = item['filename'] sanitized[filename] = item['matches'] return sanitized
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 scanner(rules: yara.Rules, options): return Scanner(rules=rules, options=options)
def test_scan_with_unscannable_file(scanner: Scanner): with make_temp_file(b'hello') as tz: results = scanner.scan_file(tz.name) assert len(results) == 0
def test_scan_with_unscannable_file(scanner: Scanner): with make_temp_file(b'hello') as tz: filename: str = os.path.basename(tz.name) results = scanner.scan_file(tz.name) assert results == {}