* Anti-analysis bypass
   - JADX fallback to DEX files on APK decompilation failure
   - apktool fallback to androguard for AndroidManifest.xml extraction
   - apksigner.jar fallback to apksigtool/androguard for signature version extraction
   - Graceful erorrs for failures instead of exceptions
This commit is contained in:
Ajin Abraham
2024-11-11 15:44:03 -08:00
committed by GitHub
parent 70e243d661
commit 3cf21cec16
15 changed files with 194 additions and 114 deletions
+6 -14
View File
@@ -1,5 +1,4 @@
# Mobile Security Framework (MobSF)
Version: v4.1
![](https://cloud.githubusercontent.com/assets/4301109/20019521/cc61f7fc-a2f2-11e6-95f3-407030d9fdde.png)
@@ -7,12 +6,10 @@ Mobile Security Framework (MobSF) is a security research platform for mobile app
Made with ![Love](https://cloud.githubusercontent.com/assets/4301109/16754758/82e3a63c-4813-11e6-9430-6015d98aeaab.png) in India
[![python](https://img.shields.io/badge/python-3.10+-blue.svg?logo=python&labelColor=yellow)](https://www.python.org/downloads/)
[![Docker Pulls](https://img.shields.io/docker/pulls/opensecurity/mobile-security-framework-mobsf?style=social)](https://hub.docker.com/r/opensecurity/mobile-security-framework-mobsf/) [![python](https://img.shields.io/badge/python-3.10+-blue.svg?logo=python&labelColor=yellow)](https://www.python.org/downloads/)
[![PyPI version](https://badge.fury.io/py/mobsf.svg)](https://badge.fury.io/py/mobsf)
[![platform](https://img.shields.io/badge/platform-osx%2Flinux%2Fwindows-green.svg)](https://github.com/MobSF/Mobile-Security-Framework-MobSF/)
[![License](https://img.shields.io/:license-GPL--3.0--only-blue.svg)](https://www.gnu.org/licenses/gpl-3.0.html)
[![Docker Pulls](https://img.shields.io/docker/pulls/opensecurity/mobile-security-framework-mobsf?style=social)](https://hub.docker.com/r/opensecurity/mobile-security-framework-mobsf/)
[![MobSF tests](https://github.com/MobSF/Mobile-Security-Framework-MobSF/workflows/MobSF%20tests/badge.svg?branch=master)](https://github.com/MobSF/Mobile-Security-Framework-MobSF/actions)
[![Quality Gate Status](https://sonarcloud.io/api/project_badges/measure?project=MobSF_Mobile-Security-Framework-MobSF&metric=alert_status)](https://sonarcloud.io/dashboard?id=MobSF_Mobile-Security-Framework-MobSF)
![GitHub closed issues](https://img.shields.io/github/issues-closed/MobSF/Mobile-Security-Framework-MobSF)
@@ -32,13 +29,14 @@ MobSF is also bundled with [Android Tamer](https://tamerplatform.com), [BlackArc
[![Donate to MobSF](https://user-images.githubusercontent.com/4301109/117404264-7aab5480-aebe-11eb-9cbd-da82d7346bb3.png)](https://opensecurity.in/donate)
If you liked MobSF and find it useful, please consider donating.
*It's easy to build open source, maintaining one is a different story. Long live open source!*
> Has MobSF made a difference for you? Show your support and help us innovate with a donation. It's easy to build open source, maintaining one is a different story.
*Long live open source!*
## Documentation
Quick setup
Quick setup with docker
```
docker pull opensecurity/mobile-security-framework-mobsf:latest
@@ -46,9 +44,6 @@ docker run -it --rm -p 8000:8000 opensecurity/mobile-security-framework-mobsf:la
```
[![See MobSF Documentation](https://user-images.githubusercontent.com/4301109/70686099-3855f780-1c79-11ea-8141-899e39459da2.png)](https://mobsf.github.io/docs)
[![See MobSF Documentation in Chinese](https://user-images.githubusercontent.com/4301109/117404947-b09d0880-aebf-11eb-9db8-3d7360f47914.png)](https://mobsf.github.io/docs/#/zh-cn/)
[![See MobSF Documentation in Japanese](https://user-images.githubusercontent.com/4301109/148662149-7ee671b4-66a2-4232-9522-276b8e88d924.png)](https://mobsf.github.io/docs/#/ja-jp/)
[![See MobSF Documentation in Español](https://user-images.githubusercontent.com/4301109/173221657-ac1f7221-6ae9-44d8-bf6b-8732d84bf120.png)](https://mobsf.github.io/docs/#/es/)
* Try MobSF Static Analyzer Online: [mobsf.live](https://mobsf.live)
* MobSF in CI/CD: [mobsfscan](https://github.com/MobSF/mobsfscan)
@@ -101,7 +96,7 @@ docker run -it --rm -p 8000:8000 opensecurity/mobile-security-framework-mobsf:la
* [Dominik Schlecht](https://github.com/sn0b4ll) ![germany](https://user-images.githubusercontent.com/4301109/37564176-743238ba-2ab6-11e8-9666-5d98f0a1d127.png)
## Honorable Contributors
## Honorable Contributors & Shoutouts
* Amrutha VC - For the new MobSF logo
* Dominik Schlecht - For the awesome work on adding Windows Phone App Static Analysis to MobSF
@@ -111,9 +106,6 @@ docker run -it --rm -p 8000:8000 opensecurity/mobile-security-framework-mobsf:la
* Abhinav Saxena - (@xandfury) - For Travis CI and Logging integration
* ![netguru](https://user-images.githubusercontent.com/4301109/76340877-a3dc4f00-62d2-11ea-8631-b4cc8d9e42ed.png) [Netguru](https://www.netguru.com/) (@karolpiateknet, @mtbrzeski) - For iOS Swift support, Rule contributions and SAST refactoring.
* Maxime Fawe - (@Arenash13) - For Matching Strategy implementation of SAST pattern matching algorithms.
## Shoutouts
* Abhinav Sejpal (@Abhinav_Sejpal) - For poking me with bugs, feature requests, and UI & UX suggestions
* Anant Srivastava (@anantshri) - For Activity Tester Idea
* Anto Joseph (@antojoseph) - For the help with SuperSU
+33 -25
View File
@@ -2,33 +2,41 @@ user nginx;
events {
worker_connections 1000;
}
http {
server {
listen 4000;
location / {
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-Port 443;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
client_max_body_size 256M;
upstream mobsf_upstream {
server mobsf:8000;
server mobsf:1337;
keepalive 16;
}
proxy_pass http://mobsf:8000;
proxy_redirect off;
proxy_read_timeout 900;
proxy_buffering on;
}
client_max_body_size 256M;
}
server {
listen 4001;
location / {
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-Port 443;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
map $server_port $forwarded_port {
4000 443;
4001 443;
}
proxy_pass http://mobsf:1337;
proxy_redirect off;
proxy_read_timeout 120;
proxy_buffering on;
}
client_max_body_size 10M;
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-Port $forwarded_port;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_redirect off;
proxy_buffering on;
server {
listen 4000;
location / {
proxy_pass http://mobsf:8000;
proxy_read_timeout 900;
client_max_body_size 256M;
}
}
server {
listen 4001;
location / {
proxy_pass http://mobsf:1337;
proxy_read_timeout 120;
client_max_body_size 10M;
}
}
}
@@ -32,6 +32,7 @@ TOP_MALWARE_PERMISSIONS = [
'android.permission.WRITE_EXTERNAL_STORAGE',
'android.permission.READ_EXTERNAL_STORAGE',
'android.permission.VIBRATE',
'android.permission.REQUEST_INSTALL_PACKAGES',
]
OTHER_PERMISSIONS = [
'android.permission.ACCESS_BACKGROUND_LOCATION',
@@ -71,7 +72,6 @@ OTHER_PERMISSIONS = [
'android.permission.READ_CALENDAR',
'android.permission.PACKAGE_USAGE_STATS',
'android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS',
'android.permission.REQUEST_INSTALL_PACKAGES',
'android.permission.WRITE_CONTACTS',
'android.permission.WRITE_SMS',
'com.android.launcher.permission.INSTALL_SHORTCUT',
+1 -1
View File
@@ -18,7 +18,7 @@ from mobsf.install.windows.setup import windows_config_local
logger = logging.getLogger(__name__)
VERSION = '4.1.8'
VERSION = '4.1.9'
BANNER = r"""
__ __ _ ____ _____ _ _ _
| \/ | ___ | |__/ ___|| ___|_ _| || | / |
@@ -152,8 +152,8 @@ def get_signature_versions(checksum, app_path, tools_dir, signed):
if re.findall(r'\(APK Signature Scheme v4\): true', out):
v4 = True
except Exception as exp:
msg = 'Failed to get signature versions'
logger.exception(msg)
msg = 'Failed to get signature versions with apksigner'
logger.error(msg)
append_scan_status(checksum, msg, repr(exp))
return v1, v2, v3, v4
@@ -166,18 +166,30 @@ def apksigtool_cert(checksum, apk_path, tools_dir):
signed = False
certs_no = 0
min_sdk = None
av1, av2, av3, av4 = None, None, None, None
try:
from apksigtool import (
APKSignatureSchemeBlock,
extract_v2_sig,
parse_apk_signing_block,
)
from apksigcopier import (
extract_meta,
)
meta = extract_meta(apk_path)
sig_files = [x.filename for x, _ in meta]
if sig_files:
av1 = True
else:
av1 = False
_, sig_block = extract_v2_sig(apk_path)
for pair in parse_apk_signing_block(sig_block).pairs:
b = pair.value
if isinstance(b, APKSignatureSchemeBlock):
signed = True
for signer in b.signers:
av2 = b.is_v2()
av3 = b.is_v3()
if b.is_v3():
min_sdk = signer.min_sdk
certs_no = len(signer.signed_data.certificates)
@@ -200,6 +212,10 @@ def apksigtool_cert(checksum, apk_path, tools_dir):
apk_path,
tools_dir,
signed)
if signed and not (v1 or v2 or v3 or v4):
# apksigner.jar failed to get signature versions
logger.info('Fetching signature versions with apksigtool')
v1, v2, v3, v4 = av1, av2, av3, av4
certlist.append(f'v1 signature: {v1}')
certlist.append(f'v2 signature: {v2}')
certlist.append(f'v3 signature: {v3}')
@@ -238,6 +254,10 @@ def get_cert_data(checksum, a, app_path, tools_dir):
app_path,
tools_dir,
signed)
if signed and not (v1 or v2 or v3 or v4):
# apksigner.jar failed to get signature versions
logger.info('Fetching signature versions with androguard')
v1, v2, v3, v4 = a.is_signed_v1(), a.is_signed_v2(), a.is_signed_v3(), None
certlist.append(f'v1 signature: {v1}')
certlist.append(f'v2 signature: {v2}')
certlist.append(f'v3 signature: {v3}')
@@ -104,6 +104,9 @@ def code_analysis(checksum, app_dir, typ, manifest_file, android_permissions):
{'.java', '.kt'},
[src],
skp)
msg = 'Android API Analysis Completed'
logger.info(msg)
append_scan_status(checksum, msg)
# Permission Mapping
rule_file = get_perm_rules(checksum, perm_rules, android_permissions)
if rule_file:
+65 -31
View File
@@ -9,6 +9,7 @@ import shutil
import subprocess
import threading
import stat
from pathlib import Path
from django.conf import settings
@@ -71,51 +72,84 @@ def dex_2_smali(checksum, app_dir, tools_dir):
def apk_2_java(checksum, app_path, app_dir, dwd_tools_dir):
"""Run jadx."""
"""Run JADX to decompile APK or all DEX files to Java source code."""
try:
jadx_version = '1.5.0'
jadx_path = f'jadx/jadx-{jadx_version}/bin/'
msg = 'Decompiling APK to Java with jadx'
jadx_base_path = Path(dwd_tools_dir) / 'jadx' / f'jadx-{jadx_version}' / 'bin'
output_dir = Path(app_dir) / 'java_source'
msg = 'Decompiling APK to Java with JADX'
logger.info(msg)
append_scan_status(checksum, msg)
args = []
output = os.path.join(app_dir, 'java_source/')
if os.path.exists(output):
# ignore WinError3 in Windows
shutil.rmtree(output, ignore_errors=True)
# Clean output directory if it exists
if output_dir.exists():
shutil.rmtree(output_dir, ignore_errors=True)
# Determine JADX executable path
if (len(settings.JADX_BINARY) > 0
and is_file_exists(settings.JADX_BINARY)):
jadx = settings.JADX_BINARY
jadx = Path(settings.JADX_BINARY)
elif platform.system() == 'Windows':
jadx = os.path.join(
dwd_tools_dir, f'{jadx_path}jadx.bat')
jadx = jadx_base_path / 'jadx.bat'
else:
jadx = os.path.join(
dwd_tools_dir, f'{jadx_path}jadx')
# Set execute permission, if JADX is not executable
if not os.access(jadx, os.X_OK):
os.chmod(jadx, stat.S_IEXEC)
jadx = jadx_base_path / 'jadx'
# Ensure JADX has execute permissions
if not os.access(str(jadx), os.X_OK):
os.chmod(str(jadx), stat.S_IEXEC)
# Prepare the base arguments for JADX
def run_jadx(arguments):
"""Run JADX command with the specified arguments."""
with open(os.devnull, 'w') as fnull:
return subprocess.run(
arguments,
stdout=fnull,
stderr=subprocess.STDOUT,
timeout=settings.JADX_TIMEOUT)
# First attempt to decompile APK
args = [
jadx,
'-ds',
output,
'-q',
'-r',
'--show-bad-code',
app_path,
]
fnull = open(os.devnull, 'w')
subprocess.run(args,
stdout=fnull,
stderr=subprocess.STDOUT,
timeout=settings.JADX_TIMEOUT)
str(jadx), '-ds', str(output_dir),
'-q', '-r', '--show-bad-code', app_path]
result = run_jadx(args)
if result.returncode == 0:
return # Success
# If APK decompilation fails, attempt to decompile all DEX files recursively
msg = 'Decompiling with JADX failed, attempting on all DEX files'
logger.warning(msg)
append_scan_status(checksum, msg)
dex_files = Path(app_path).parent.rglob('*.dex')
decompile_failed = False
for dex_file in dex_files:
msg = f'Decompiling {dex_file.name} with JADX'
logger.info(msg)
append_scan_status(checksum, msg)
# Update argument to point to the current DEX file
args[-1] = str(dex_file)
result_dex = run_jadx(args)
if result_dex.returncode != 0:
decompile_failed = True
msg = f'Decompiling with JADX failed for {dex_file.name}'
logger.error(msg)
append_scan_status(checksum, msg)
if decompile_failed:
msg = 'Some DEX files failed to decompile'
logger.error(msg)
append_scan_status(checksum, msg)
except subprocess.TimeoutExpired as exp:
msg = 'Decompiling with jadx timed out'
msg = 'Decompiling with JADX timed out'
logger.warning(msg)
append_scan_status(checksum, msg, repr(exp))
except Exception as exp:
msg = 'Decompiling with jadx failed'
msg = 'Decompiling with JADX failed'
logger.exception(msg)
append_scan_status(checksum, msg, repr(exp))
@@ -114,6 +114,7 @@ def common_analysis(request, app_dic, rescan, api, analysis_type):
app_dic['app_dir'],
app_dic['tools_dir'],
'aar',
apk,
)
app_dic['manifest_file'] = mani_file
app_dic['ns'] = ns
@@ -31,7 +31,7 @@ ANDROID_8_0_LEVEL = 26
ANDROID_MANIFEST_FILE = 'AndroidManifest.xml'
def get_manifest_file(app_dir, app_path, tools_dir, typ):
def get_manifest_file(app_dir, app_path, tools_dir, typ, apk):
"""Read the manifest file."""
try:
manifest = ''
@@ -40,7 +40,7 @@ def get_manifest_file(app_dir, app_path, tools_dir, typ):
manifest = os.path.join(app_dir, ANDROID_MANIFEST_FILE)
elif typ == 'apk':
logger.info('Getting AndroidManifest.xml from APK')
manifest = get_manifest_apk(app_path, app_dir, tools_dir)
manifest = get_manifest_apk(app_path, app_dir, tools_dir, apk)
else:
logger.info('Getting AndroidManifest.xml from Source Code')
if typ == 'eclipse':
@@ -54,7 +54,21 @@ def get_manifest_file(app_dir, app_path, tools_dir, typ):
logger.exception('Getting AndroidManifest.xml file')
def get_manifest_apk(app_path, app_dir, tools_dir):
def get_android_manifest_androguard(apk, app_dir):
"""Get AndroidManifest.xml using Androguard."""
try:
logger.info('Extracting AndroidManifest.xml with Androguard')
manifest = apk.get_android_manifest_axml()
if not manifest:
return
manifest_file = Path(app_dir) / 'apktool_out' / ANDROID_MANIFEST_FILE
manifest_file.write_bytes(manifest.get_xml())
except Exception:
logger.exception('Error Extracting AndroidManifest.xml with Androguard')
return None
def get_manifest_apk(app_path, app_dir, tools_dir, apk):
"""Get readable AndroidManifest.xml.
Should be called before get_icon_apk() function
@@ -83,7 +97,11 @@ def get_manifest_apk(app_path, app_dir, tools_dir):
# APKTool already created readable XML
return manifest
logger.info('Converting AXML to XML')
subprocess.check_output(args) # User input is MD5 and validated
subprocess.check_output(args)
except subprocess.CalledProcessError:
# APK tool failed
logger.warning('apktool failed to extract AndroidManifest.xml')
get_android_manifest_androguard(apk, app_dir)
except Exception:
logger.exception('Getting Manifest file')
return manifest
@@ -120,7 +138,7 @@ def bs4_xml_parser(xml_str):
return None
def get_manifest(checksum, app_path, app_dir, tools_dir, typ):
def get_manifest(checksum, app_path, app_dir, tools_dir, typ, apk):
"""Get the manifest file."""
try:
ns = 'android'
@@ -128,7 +146,8 @@ def get_manifest(checksum, app_path, app_dir, tools_dir, typ):
app_dir,
app_path,
tools_dir,
typ)
typ,
apk)
mfile = Path(manifest_file)
if not mfile.exists():
logger.warning('apktool failed to extract '
@@ -214,16 +214,6 @@ def static_analyzer(request, checksum, api=False):
app_dic['certz'] = get_hardcoded_cert_keystore(
checksum,
app_dic['files'])
# Manifest XML
mani_file, ns, mani_xml = get_manifest(
checksum,
app_dic['app_path'],
app_dic['app_dir'],
app_dic['tools_dir'],
APK_TYPE,
)
app_dic['manifest_file'] = mani_file
app_dic['parsed_xml'] = mani_xml
# Parse APK with Androguard
apk = parse_apk(
checksum,
@@ -234,6 +224,17 @@ def static_analyzer(request, checksum, api=False):
app_dic['app_dir'],
True,
)
# Manifest XML
mani_file, ns, mani_xml = get_manifest(
checksum,
app_dic['app_path'],
app_dic['app_dir'],
app_dic['tools_dir'],
APK_TYPE,
apk,
)
app_dic['manifest_file'] = mani_file
app_dic['parsed_xml'] = mani_xml
# Manifest data extraction
man_data_dic = manifest_data(
checksum,
@@ -424,6 +425,12 @@ def static_analyzer(request, checksum, api=False):
app_dic['certz'] = get_hardcoded_cert_keystore(
checksum,
app_dic['files'])
# get app_name
app_dic['real_name'] = get_app_name(
app_dic['app_path'],
app_dic['app_dir'],
False,
)
# Manifest XML
mani_file, ns, mani_xml = get_manifest(
checksum,
@@ -431,15 +438,10 @@ def static_analyzer(request, checksum, api=False):
app_dic['app_dir'],
app_dic['tools_dir'],
pro_type,
None,
)
app_dic['manifest_file'] = mani_file
app_dic['parsed_xml'] = mani_xml
# get app_name
app_dic['real_name'] = get_app_name(
app_dic['app_path'],
app_dic['app_dir'],
False,
)
# Get manifest data
man_data_dic = manifest_data(
checksum,
@@ -39,7 +39,8 @@ def run(request, checksum):
app_dir,
app_path,
tools_dir,
typ)
typ,
None)
mfile = Path(manifest_file)
if mfile.exists():
manifest = mfile.read_text('utf-8', 'ignore')
@@ -93,15 +93,15 @@ def unzip(checksum, app_path, ext_path):
zipptr.extract(filename, ext_path)
return files
except Exception as exp:
msg = 'Unzipping Error'
logger.exception(msg)
msg = f'Unzipping Error - {str(exp)}'
logger.error(msg)
append_scan_status(checksum, msg, repr(exp))
if platform.system() == 'Windows':
msg = 'Unzipping Error. Not yet implemented in Windows'
logger.warning(msg)
append_scan_status(checksum, msg)
else:
msg = 'Unzipping Error. Trying with OS unzip utility'
msg = 'Attempting to unzip with OS unzip utility'
logger.info(msg)
append_scan_status(checksum, msg)
try:
@@ -88,7 +88,7 @@ textarea:focus {
<div class="col-md-9">
<h4>MobSF Dynamic Analyzer Supports</h4>
<h5>
<strong>• Genymotion Android VM</strong> version 4.1 - 11.0 (arm64, x86, upto API 30)<br/>
<strong>• Genymotion Android VM</strong> version 4.1 - 11.0 (arm64, x86, and x86_64 upto API 30)<br/>
<strong>• Android Emulator AVD</strong> (non production) version 5.0 - 11.0 (arm, arm64, x86, and x86_64 upto API 30)<br/>
<strong>• Corellium Android VM</strong> (userdebug builds) version 7.1.2 - 11.0 (arm64 upto API 30)
</h5>
Generated
+12 -12
View File
@@ -2630,23 +2630,23 @@ tests = ["coverage[toml] (>=5.0.2)", "pytest"]
[[package]]
name = "setuptools"
version = "75.3.0"
version = "75.4.0"
description = "Easily download, build, install, upgrade, and uninstall Python packages"
optional = false
python-versions = ">=3.8"
python-versions = ">=3.9"
files = [
{file = "setuptools-75.3.0-py3-none-any.whl", hash = "sha256:f2504966861356aa38616760c0f66568e535562374995367b4e69c7143cf6bcd"},
{file = "setuptools-75.3.0.tar.gz", hash = "sha256:fba5dd4d766e97be1b1681d98712680ae8f2f26d7881245f2ce9e40714f1a686"},
{file = "setuptools-75.4.0-py3-none-any.whl", hash = "sha256:b3c5d862f98500b06ffdf7cc4499b48c46c317d8d56cb30b5c8bce4d88f5c216"},
{file = "setuptools-75.4.0.tar.gz", hash = "sha256:1dc484f5cf56fd3fe7216d7b8df820802e7246cfb534a1db2aa64f14fcb9cdcb"},
]
[package.extras]
check = ["pytest-checkdocs (>=2.4)", "pytest-ruff (>=0.2.1)", "ruff (>=0.5.2)"]
core = ["importlib-metadata (>=6)", "importlib-resources (>=5.10.2)", "jaraco.collections", "jaraco.functools", "jaraco.text (>=3.7)", "more-itertools", "more-itertools (>=8.8)", "packaging", "packaging (>=24)", "platformdirs (>=4.2.2)", "tomli (>=2.0.1)", "wheel (>=0.43.0)"]
check = ["pytest-checkdocs (>=2.4)", "pytest-ruff (>=0.2.1)", "ruff (>=0.7.0)"]
core = ["importlib-metadata (>=6)", "jaraco.collections", "jaraco.functools (>=4)", "jaraco.text (>=3.7)", "more-itertools", "more-itertools (>=8.8)", "packaging", "packaging (>=24.2)", "platformdirs (>=4.2.2)", "tomli (>=2.0.1)", "wheel (>=0.43.0)"]
cover = ["pytest-cov"]
doc = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "pygments-github-lexers (==0.0.5)", "pyproject-hooks (!=1.1)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-favicon", "sphinx-inline-tabs", "sphinx-lint", "sphinx-notfound-page (>=1,<2)", "sphinx-reredirects", "sphinxcontrib-towncrier", "towncrier (<24.7)"]
enabler = ["pytest-enabler (>=2.2)"]
test = ["build[virtualenv] (>=1.0.3)", "filelock (>=3.4.0)", "ini2toml[lite] (>=0.14)", "jaraco.develop (>=7.21)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "jaraco.test (>=5.5)", "packaging (>=23.2)", "pip (>=19.1)", "pyproject-hooks (!=1.1)", "pytest (>=6,!=8.1.*)", "pytest-home (>=0.5)", "pytest-perf", "pytest-subprocess", "pytest-timeout", "pytest-xdist (>=3)", "tomli-w (>=1.0.0)", "virtualenv (>=13.0.0)", "wheel (>=0.44.0)"]
type = ["importlib-metadata (>=7.0.2)", "jaraco.develop (>=7.21)", "mypy (==1.12.*)", "pytest-mypy"]
test = ["build[virtualenv] (>=1.0.3)", "filelock (>=3.4.0)", "ini2toml[lite] (>=0.14)", "jaraco.develop (>=7.21)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "jaraco.test (>=5.5)", "packaging (>=24.2)", "pip (>=19.1)", "pyproject-hooks (!=1.1)", "pytest (>=6,!=8.1.*)", "pytest-home (>=0.5)", "pytest-perf", "pytest-subprocess", "pytest-timeout", "pytest-xdist (>=3)", "tomli-w (>=1.0.0)", "virtualenv (>=13.0.0)", "wheel (>=0.44.0)"]
type = ["importlib-metadata (>=7.0.2)", "jaraco.develop (>=7.21)", "mypy (>=1.12,<1.14)", "pytest-mypy"]
[[package]]
name = "shelljob"
@@ -3263,13 +3263,13 @@ files = [
[[package]]
name = "zipp"
version = "3.20.2"
version = "3.21.0"
description = "Backport of pathlib-compatible object wrapper for zip files"
optional = false
python-versions = ">=3.8"
python-versions = ">=3.9"
files = [
{file = "zipp-3.20.2-py3-none-any.whl", hash = "sha256:a817ac80d6cf4b23bf7f2828b7cabf326f15a001bea8b1f9b49631780ba28350"},
{file = "zipp-3.20.2.tar.gz", hash = "sha256:bc9eb26f4506fda01b81bcde0ca78103b6e62f991b381fec825435c836edbc29"},
{file = "zipp-3.21.0-py3-none-any.whl", hash = "sha256:ac1bbe05fd2991f160ebce24ffbac5f6d11d83dc90891255885223d42b3cd931"},
{file = "zipp-3.21.0.tar.gz", hash = "sha256:2c9958f6430a2040341a52eb608ed6dd93ef4392e02ffe219417c1b28b5dd1f4"},
]
[package.extras]
+1 -1
View File
@@ -1,6 +1,6 @@
[tool.poetry]
name = "mobsf"
version = "4.1.8"
version = "4.1.9"
description = "Mobile Security Framework (MobSF) is an automated, all-in-one mobile application (Android/iOS/Windows) pen-testing, malware analysis and security assessment framework capable of performing static and dynamic analysis."
keywords = ["mobsf", "mobile security framework", "mobile security", "security tool", "static analysis", "dynamic analysis", "malware analysis"]
authors = ["Ajin Abraham <[email protected]>"]