Files
Mobile-Security-Framework-M…/mobsf/StaticAnalyzer/views/android/strings.py
T
Ajin Abraham 2854114b28 [HOTFIX][EFR06] Independent Shared Object (.so) Scan and Improved String search (#2228)
* String extraction from APK, Source, AAR, JAR, SO
* Strings sections to show source of strings extracted
* Strings Refactor
* Support for independent .SO scan
* Android SCA rules update
* Entropies scan support for strings
* URLs/Email extraction refactor
* Bug Fixes
  * iOS Source Report Fix
  * Frida APK Patcher (WIP)
  * Dynamic Analyzer identifier not available
  * Settings env var not working fix for enabled by default features
  * AppSec Score fix
  * Recent `scan not completed` fix for iOS zip
2023-08-14 11:47:55 -07:00

148 lines
4.7 KiB
Python
Executable File

# -*- coding: utf_8 -*-
"""Module for strings-method for java."""
import logging
import os
from pathlib import Path
from androguard.core.bytecodes import apk
from mobsf.StaticAnalyzer.views.common.shared_func import (
is_secret_key,
strings_and_entropies,
url_n_email_extract,
)
from mobsf.StaticAnalyzer.views.common.entropy import (
get_entropies,
)
from mobsf.MobSF.utils import (
get_android_src_dir,
)
logger = logging.getLogger(__name__)
logging.getLogger('androguard').setLevel(logging.ERROR)
def strings_from_so(elf_strings):
"""Extract Strings from so file."""
sos = []
try:
for solib in elf_strings:
for so, str_list in solib.items():
if not str_list:
continue
# extract url, email
so_str = ' '.join(str_list)
so_urls, so_urls_nf, so_emails_nf = url_n_email_extract(
so_str, so)
sos.append({so: {
'secrets': list(get_entropies(so_str)),
'strings': list(set(str_list)),
'urls_list': so_urls,
'urls_nf': so_urls_nf,
'emails_nf': so_emails_nf,
}})
except Exception:
logger.exception('Extracting Data from SO')
return sos
def strings_from_apk(app_file, app_dir):
"""Extract Strings from an APK."""
dat = []
secrets = []
urls = []
urls_nf = []
emails_nf = []
try:
logger.info('Extracting Data from APK')
apk_file = os.path.join(app_dir, app_file)
and_a = apk.APK(apk_file)
rsrc = and_a.get_android_resources()
if rsrc:
pkg = rsrc.get_packages_names()[0]
rsrc.get_strings_resources()
for i in rsrc.values[pkg].keys():
res_string = rsrc.values[pkg][i].get('string')
if not res_string:
continue
for duo in res_string:
cap_str = '"' + duo[0] + '" : "' + duo[1] + '"'
# Extract possible secret holding keys
if is_secret_key(duo[0] + '"') and ' ' not in duo[1]:
secrets.append(cap_str)
dat.append(cap_str)
# Extract URLs and Emails from Android String Resources
urls, urls_nf, emails_nf = url_n_email_extract(
''.join(dat), 'Android String Resource')
except Exception:
logger.exception('Extracting Data from APK')
return {
'strings': list(set(dat)),
'urls_list': urls,
'urls_nf': urls_nf,
'emails_nf': emails_nf,
'secrets': secrets,
}
def strings_from_code(src_dir, typ, exts):
"""Extract Strings and Secrets from Java/Kotlin code."""
data = {
'strings': set(),
'secrets': set(),
}
try:
src_dir = get_android_src_dir(Path(src_dir), typ)
data = strings_and_entropies(src_dir, exts)
except Exception:
logger.exception('Extracting Data from Code')
return data
def get_strings_metadata(app_file, app_dir, elf_strings, typ, exts, code_dic):
"""Get Strings, secrets, entropies, URLs, emails."""
strings = {
'strings_apk_res': {},
'strings_so': [],
'strings_code': {},
}
urls_list = []
urls_n_files = []
emails_n_files = []
secrets = []
if app_file:
# APK
apk_res = strings_from_apk(app_file, app_dir)
strings['strings_apk_res'] = apk_res['strings']
urls_list.extend(apk_res['urls_list'])
urls_n_files.extend(apk_res['urls_nf'])
emails_n_files.extend(apk_res['emails_nf'])
secrets.extend(apk_res['secrets'])
if elf_strings:
# ELF (.so) by file
sos = strings_from_so(elf_strings)
so_strings = []
for so in sos:
for so_file, s in so.items():
so_strings.append({so_file: s['strings']})
urls_list.extend(s['urls_list'])
urls_n_files.extend(s['urls_nf'])
emails_n_files.extend(s['emails_nf'])
secrets.extend(s['secrets'])
secrets = list(set(secrets))
strings['strings_so'] = so_strings
if exts:
# Source Code
code_res = strings_from_code(app_dir, typ, exts)
strings['strings_code'] = list(code_res['strings'])
secrets.extend(code_res['secrets'])
code_dic['strings'] = strings
code_dic['secrets'] = list(secrets)
# Code Analysis has urls, urlsnfiles and emailsnfiles
code_dic['urls'].extend(urls_n_files)
code_dic['emails'].extend(emails_n_files)
code_dic['urls_list'].extend(urls_list)
code_dic['urls_list'] = list(set(code_dic['urls_list']))