* APKID QA.
* Bash and Batch file script QA.
* Android Report template optimizations on how exported components are displayed.
* Clickable Android Activities, Services, Providers and Recievers.
* Updated Android version support to 11.0 for Android Studio AVD.
* Created helper scripts for AVDs `scripts/start_avd.sh` and `scripts/start_avd.ps1`.
This commit is contained in:
Ajin Abraham
2024-11-10 00:44:20 -08:00
committed by GitHub
parent 76596e33ed
commit 70e243d661
17 changed files with 501 additions and 421 deletions
+3 -4
View File
@@ -1,6 +1,6 @@
# -*- coding: utf_8 -*-
import logging
import os
from pathlib import Path
from django.conf import settings
@@ -24,9 +24,6 @@ def apkid_analysis(checksum, apk_file):
logger.error(msg)
append_scan_status(checksum, msg, repr(exp))
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
@@ -87,5 +84,7 @@ def apkid_analysis(checksum, apk_file):
filename = item['filename']
if '!' in filename:
filename = filename.split('!', 1)[1]
else:
filename = Path(filename).name
sanitized[filename] = item['matches']
return sanitized
+1 -1
View File
@@ -18,7 +18,7 @@ from mobsf.install.windows.setup import windows_config_local
logger = logging.getLogger(__name__)
VERSION = '4.1.7'
VERSION = '4.1.8'
BANNER = r"""
__ __ _ ____ _____ _ _ _
| \/ | ___ | |__/ ___|| ___|_ _| || | / |
+3 -2
View File
@@ -14,7 +14,8 @@ from urllib.request import (
logging.basicConfig(
level=logging.INFO,
format='%(asctime)s - %(levelname)s - %(message)s')
format='[%(levelname)s] %(asctime)-15s - %(message)s',
datefmt='%d/%b/%Y %H:%M:%S')
logger = logging.getLogger(__name__)
@@ -41,7 +42,7 @@ def download_file(url, file_path):
# Print progress
if file_size > 0:
done = int(50 * downloaded / file_size)
fmt = (f'\r[{"#" * done}{"-" * (50-done)}] '
fmt = (f'\r[{"#" * done}{"-" * (50 - done)}] '
f'{downloaded * 100 / file_size:.2f}%')
sys.stdout.write(fmt)
sys.stdout.flush()
+5
View File
@@ -752,6 +752,11 @@ def replace(value, arg):
return value.replace(what, to)
def pathify(value):
"""Convert to path."""
return value.replace('.', '/')
def relative_path(value):
"""Show relative path to two parents."""
sep = None
@@ -28,6 +28,7 @@ from mobsf.MobSF.utils import (
is_file_exists,
is_md5,
key,
pathify,
print_n_send_error_response,
relative_path,
)
@@ -107,6 +108,7 @@ logger = logging.getLogger(__name__)
register.filter('key', key)
register.filter('android_component', android_component)
register.filter('relative_path', relative_path)
register.filter('pathify', pathify)
@login_required
+8
View File
@@ -0,0 +1,8 @@
{% if list|length != 0 %}
<details {% if list|length < limit %}open{% endif %}>
<summary>{% if list|length < limit %}Showing{% else %}Show{% endif %} all <strong>{{ list | length }}</strong> {{ type }}</summary>
{% for val in list %}
<a href="{% url "view_source" %}?file={{ val | pathify }}.java&amp;md5={{ md5 }}&amp;type={{app_type}}"> {{ val }}</a><br/>
{% endfor %}
</details>
{% endif %}
@@ -89,13 +89,13 @@ textarea:focus {
<h4>MobSF Dynamic Analyzer Supports</h4>
<h5>
<strong>• Genymotion Android VM</strong> version 4.1 - 11.0 (arm64, x86, upto API 30)<br/>
<strong>• Android Emulator AVD</strong> (non production) version 5.0 - 9.0 (arm, arm64, x86, and x86_64 upto API 28)<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>
<p>
{% if android_version %}
Android version >= <strong>9.0</strong> recommended<br/>
Detected Android Version: <strong>{{android_version}}</strong>, SDK: <strong>{{ android_sdk }}</strong> <br/>
Detected Android Version: <strong>{{android_version}}</strong>, SDK: API level <strong>{{ android_sdk }}</strong> <br/>
{% if android_sdk|floatformat > android_supported|floatformat %}
<script src="{% static "adminlte/plugins/sweetalert2/sweetalert2.min.js" %}"></script>
<script>
@@ -529,14 +529,14 @@
<!-- small box -->
<div class="small-box bg-info">
<div class="inner">
<h3>{{ activities | length }}</h3>
<h3> {{ exported_count.exported_activities }} / {{ activities | length }}</h3>
<p>ACTIVITIES</p>
<p>EXPORTED ACTIVITIES</p>
</div>
<div class="icon">
<i class="fa fa-language"></i>
</div>
<a href="#activities" class="small-box-footer">View <i class="fas fa-arrow-circle-down"></i></a>
<a href="#activities" class="small-box-footer">View All <i class="fas fa-arrow-circle-down"></i></a>
</div>
</div>
<!-- ./col -->
@@ -544,14 +544,14 @@
<!-- small box -->
<div class="small-box bg-success">
<div class="inner">
<h3>{{ services | length }}</h3>
<h3>{{ exported_count.exported_services }} / {{ services | length }}</h3>
<p>SERVICES</p>
<p>EXPORTED SERVICES</p>
</div>
<div class="icon">
<i class="fa fa-cogs"></i>
</div>
<a href="#services" class="small-box-footer">View <i class="fas fa-arrow-circle-down"></i></a>
<a href="#services" class="small-box-footer">View All <i class="fas fa-arrow-circle-down"></i></a>
</div>
</div>
<!-- ./col -->
@@ -559,14 +559,14 @@
<!-- small box -->
<div class="small-box bg-warning">
<div class="inner">
<h3>{{ receivers | length }}</h3>
<h3>{{ exported_count.exported_receivers }} / {{ receivers | length }}</h3>
<p>RECEIVERS</p>
<p>EXPORTED RECEIVERS</p>
</div>
<div class="icon">
<i class="fa fa-assistive-listening-systems"></i>
</div>
<a href="#receivers" class="small-box-footer">View <i class="fas fa-arrow-circle-down"></i></a>
<a href="#receivers" class="small-box-footer">View All <i class="fas fa-arrow-circle-down"></i></a>
</div>
</div>
<!-- ./col -->
@@ -574,74 +574,17 @@
<!-- small box -->
<div class="small-box bg-danger">
<div class="inner">
<h3>{{ providers | length }}</h3>
<h3>{{exported_count.exported_providers}} / {{ providers | length }}</h3>
<p>PROVIDERS</p>
<p>EXPORTED PROVIDERS</p>
</div>
<div class="icon">
<i class="fa fa-database"></i>
</div>
<a href="#providers" class="small-box-footer">View <i class="fas fa-arrow-circle-down"></i></a>
<a href="#providers" class="small-box-footer">View All <i class="fas fa-arrow-circle-down"></i></a>
</div>
<!-- /.row -->
</div><!-- /.container-fluid -->
<div class="col-12 col-sm-6 col-md-3">
<div class="info-box">
<span class="info-box-icon bg-info elevation-1"><i class="fas fa-language"></i></span>
<div class="info-box-content">
<span class="info-box-text">Exported <br/>Activities</span>
<span class="info-box-number">
{{ exported_count.exported_activities }}
</span>
</div>
<!-- /.info-box-content -->
</div>
<!-- /.info-box -->
</div>
<!-- /.col -->
<div class="col-12 col-sm-6 col-md-3">
<div class="info-box mb-3">
<span class="info-box-icon bg-success elevation-1"><i class="fas fa-cogs"></i></span>
<div class="info-box-content">
<span class="info-box-text">Exported <br/>Services</span>
<span class="info-box-number">{{ exported_count.exported_services }}</span>
</div>
<!-- /.info-box-content -->
</div>
<!-- /.info-box -->
</div>
<!-- /.col -->
<!-- fix for small devices only -->
<div class="clearfix hidden-md-up"></div>
<div class="col-12 col-sm-6 col-md-3">
<div class="info-box mb-3">
<span class="info-box-icon bg-warning elevation-1"><i class="fas fa-assistive-listening-systems"></i></span>
<div class="info-box-content">
<span class="info-box-text">Exported <br/>Receivers</span>
<span class="info-box-number">{{ exported_count.exported_receivers }}</span>
</div>
<!-- /.info-box-content -->
</div>
<!-- /.info-box -->
</div>
<!-- /.col -->
<div class="col-12 col-sm-6 col-md-3">
<div class="info-box mb-3">
<span class="info-box-icon bg-danger elevation-1"><i class="fas fa-database"></i></span>
<div class="info-box-content">
<span class="info-box-text">Exported <br/>Providers</span>
<span class="info-box-number">{{exported_count.exported_providers}}</span>
</div>
<!-- /.info-box-content -->
</div>
<!-- /.info-box -->
</div>
</div>
</div>
</div>
@@ -2234,7 +2177,7 @@
</p>
<div class="list-group">
<p>
{% include 'base/list.html' with list=activities type="activities" limit=50 %}
{% include 'base/list_href.html' with list=activities type="activities" limit=50 %}
</p>
</div>
</div>
@@ -2257,7 +2200,7 @@
</p>
<div class="list-group">
<p>
{% include 'base/list.html' with list=services type="services" limit=50 %}
{% include 'base/list_href.html' with list=services type="services" limit=50 %}
</p>
</div>
</div>
@@ -2280,7 +2223,7 @@
</p>
<div class="list-group">
<p>
{% include 'base/list.html' with list=receivers type="receivers" limit=50 %}
{% include 'base/list_href.html' with list=receivers type="receivers" limit=50 %}
</p>
</div>
</div>
@@ -2304,7 +2247,7 @@
</p>
<div class="list-group">
<p>
{% include 'base/list.html' with list=providers type="providers" limit=50 %}
{% include 'base/list_href.html' with list=providers type="providers" limit=50 %}
</p>
</div>
</div>
@@ -400,140 +400,83 @@
</div>
<!-- Boxes -->
<div class="container-fluid">
<div class="row">
<div class="col-lg-12">
<div class="card">
<div class="card-body">
<h5 class="card-title"></h5>
<div class="row">
<!-- Boxes columns -->
<div class="col-12 col-sm-6 col-md-3">
<!-- small box -->
<div class="small-box bg-info">
<div class="inner">
<h3>{{ activities | length }}</h3>
<div class="container-fluid">
<div class="row">
<div class="col-lg-12">
<p>ACTIVITIES</p>
</div>
<div class="icon">
<i class="fa fa-language"></i>
</div>
<a href="#activities" class="small-box-footer">View <i class="fas fa-arrow-circle-down"></i></a>
<div class="card">
<div class="card-body">
<h5 class="card-title"></h5>
<div class="row">
<!-- Boxes columns -->
<div class="col-12 col-sm-6 col-md-3">
<!-- small box -->
<div class="small-box bg-info">
<div class="inner">
<h3> {{ exported_count.exported_activities }} / {{ activities | length }}</h3>
<p>EXPORTED ACTIVITIES</p>
</div>
<div class="icon">
<i class="fa fa-language"></i>
</div>
<a href="#activities" class="small-box-footer">View All <i class="fas fa-arrow-circle-down"></i></a>
</div>
<!-- ./col -->
<div class="col-12 col-sm-6 col-md-3">
<!-- small box -->
<div class="small-box bg-success">
<div class="inner">
<h3>{{ services | length }}</h3>
</div>
<!-- ./col -->
<div class="col-12 col-sm-6 col-md-3">
<!-- small box -->
<div class="small-box bg-success">
<div class="inner">
<h3>{{ exported_count.exported_services }} / {{ services | length }}</h3>
<p>SERVICES</p>
</div>
<div class="icon">
<i class="fa fa-cogs"></i>
</div>
<a href="#services" class="small-box-footer">View <i class="fas fa-arrow-circle-down"></i></a>
<p>EXPORTED SERVICES</p>
</div>
<div class="icon">
<i class="fa fa-cogs"></i>
</div>
<a href="#services" class="small-box-footer">View All <i class="fas fa-arrow-circle-down"></i></a>
</div>
<!-- ./col -->
<div class="col-12 col-sm-6 col-md-3">
<!-- small box -->
<div class="small-box bg-warning">
<div class="inner">
<h3>{{ receivers | length }}</h3>
</div>
<!-- ./col -->
<div class="col-12 col-sm-6 col-md-3">
<!-- small box -->
<div class="small-box bg-warning">
<div class="inner">
<h3>{{ exported_count.exported_receivers }} / {{ receivers | length }}</h3>
<p>RECEIVERS</p>
</div>
<div class="icon">
<i class="fa fa-assistive-listening-systems"></i>
</div>
<a href="#receivers" class="small-box-footer">View <i class="fas fa-arrow-circle-down"></i></a>
<p>EXPORTED RECEIVERS</p>
</div>
<div class="icon">
<i class="fa fa-assistive-listening-systems"></i>
</div>
<a href="#receivers" class="small-box-footer">View All <i class="fas fa-arrow-circle-down"></i></a>
</div>
<!-- ./col -->
<div class="col-12 col-sm-6 col-md-3">
<!-- small box -->
<div class="small-box bg-danger">
<div class="inner">
<h3>{{ providers | length }}</h3>
</div>
<!-- ./col -->
<div class="col-12 col-sm-6 col-md-3">
<!-- small box -->
<div class="small-box bg-danger">
<div class="inner">
<h3>{{exported_count.exported_providers}} / {{ providers | length }}</h3>
<p>PROVIDERS</p>
</div>
<div class="icon">
<i class="fa fa-database"></i>
</div>
<a href="#providers" class="small-box-footer">View <i class="fas fa-arrow-circle-down"></i></a>
<p>EXPORTED PROVIDERS</p>
</div>
<!-- /.row -->
</div><!-- /.container-fluid -->
<div class="col-12 col-sm-6 col-md-3">
<div class="info-box">
<span class="info-box-icon bg-info elevation-1"><i class="fas fa-language"></i></span>
<div class="info-box-content">
<span class="info-box-text">Exported <br/>Activities</span>
<span class="info-box-number">
{{ exported_count.exported_activities }}
</span>
</div>
<!-- /.info-box-content -->
<div class="icon">
<i class="fa fa-database"></i>
</div>
<!-- /.info-box -->
<a href="#providers" class="small-box-footer">View All <i class="fas fa-arrow-circle-down"></i></a>
</div>
<!-- /.col -->
<div class="col-12 col-sm-6 col-md-3">
<div class="info-box mb-3">
<span class="info-box-icon bg-success elevation-1"><i class="fas fa-cogs"></i></span>
<div class="info-box-content">
<span class="info-box-text">Exported <br/>Services</span>
<span class="info-box-number">{{ exported_count.exported_services }}</span>
</div>
<!-- /.info-box-content -->
</div>
<!-- /.info-box -->
</div>
<!-- /.col -->
<!-- fix for small devices only -->
<div class="clearfix hidden-md-up"></div>
<div class="col-12 col-sm-6 col-md-3">
<div class="info-box mb-3">
<span class="info-box-icon bg-warning elevation-1"><i class="fas fa-assistive-listening-systems"></i></span>
<div class="info-box-content">
<span class="info-box-text">Exported <br/>Receivers</span>
<span class="info-box-number">{{ exported_count.exported_receivers}}</span>
</div>
<!-- /.info-box-content -->
</div>
<!-- /.info-box -->
</div>
<!-- /.col -->
<div class="col-12 col-sm-6 col-md-3">
<div class="info-box mb-3">
<span class="info-box-icon bg-danger elevation-1"><i class="fas fa-database"></i></span>
<div class="info-box-content">
<span class="info-box-text">Exported <br/>Providers</span>
<span class="info-box-number">{{ exported_count.exported_providers }}</span>
</div>
<!-- /.info-box-content -->
</div>
<!-- /.info-box -->
</div>
</div>
</div>
<!-- /.row -->
</div><!-- /.container-fluid -->
</div>
</div>
</div>
</div>
</div>
</section>
</div>
</div>
</section>
<!-- =========================end information==================================== -->
+1 -1
View File
@@ -1,6 +1,6 @@
[tool.poetry]
name = "mobsf"
version = "4.1.7"
version = "4.1.8"
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]>"]
+25 -39
View File
@@ -1,49 +1,35 @@
#!/bin/bash
var="$1"
function validate_ip () {
local IP=$1
local stat=1
if [[ $IP =~ ^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$ ]]; then
OIFS=$IFS
IFS='.'
ip=($IP)
IFS=$OIFS
[[ ${ip[0]} -le 255 && ${ip[1]} -le 255 \
&& ${ip[2]} -le 255 && ${ip[3]} -le 255 ]]
stat=$?
fi
if [ "$stat" -eq 0 ]; then
return $stat
else
echo 'Bad IP'
exit 1
fi
function validate_ip() {
local IP=$1
if [[ $IP =~ ^([0-9]{1,3}\.){3}[0-9]{1,3}$ ]]; then
for i in ${IP//./ }; do
((i >= 0 && i <= 255)) || { echo 'Bad IP'; exit 1; }
done
else
echo 'Bad IP'
exit 1
fi
}
function validate_port () {
local PORT=$1
if [ -z "$PORT" ]; then
echo 'Port can not be empty'
exit 1
fi
if [ "$PORT" -gt 1024 ] && [ "$PORT" -lt 65535 ]; then
return 0
else
echo 'Invalid Port'
exit 1
fi
function validate_port() {
local PORT=$1
if [[ -z "$PORT" || "$PORT" -le 1024 || "$PORT" -ge 65535 ]]; then
echo 'Invalid Port'
exit 1
fi
}
if [ ! -z "$var" ]; then
IP=$(echo $var | awk -F':' '{print $1}')
PORT=$(echo $var | awk -F':' '{print $2}')
validate_ip $IP
validate_port $PORT
else
if [[ -n "$var" ]]; then
IP="${var%%:*}"
PORT="${var##*:}"
validate_ip "$IP"
validate_port "$PORT"
else
IP='[::]'
PORT='8000'
fi
fi
python3 -m poetry run gunicorn -b ${IP}:${PORT} mobsf.MobSF.wsgi:application --workers=1 --threads=10 --timeout=3600 \
--log-level=citical --log-file=- --access-logfile=- --error-logfile=- --capture-output
--log-level=critical --log-file=- --access-logfile=- --error-logfile=- --capture-output
+35 -35
View File
@@ -1,35 +1,35 @@
@echo off
echo =======================MobSF Clean Script for Windows=======================
echo Running this script will delete the Scan database, all files uploaded and generated.
SET mobsf_home="%userprofile%\.MobSF"
SET mypath=%~dp0
echo %mypath:~0,-1%
IF "%~1"=="y" (
echo Deleting all uploads
rmdir "mobsf\uploads" /q /s >nul 2>&1
echo Deleting all downloads
rmdir "mobsf\downloads" /q /s >nul 2>&1
echo Deleting Static Analyzer migrations
rmdir "mobsf\StaticAnalyzer\migrations" /q /s >nul 2>&1
echo Deleting Dynamic Analyzer migrations
rmdir "mobsf\DynamicAnalyzer\migrations" /q /s >nul 2>&1
echo Deleting MobSF migrations
rmdir "mobsf\MobSF\migrations" /q /s >nul 2>&1
echo Deleting temp and log files
del /f "mobsf\debug.log" >nul 2>&1
del /f "classes*" >nul 2>&1
echo Deleting Scan database
del /f "mobsf\db.sqlite3" >nul 2>&1
echo Deleting Secret file
del /f "mobsf\secret" >nul 2>&1
echo Deleting Previous setup files
rmdir "%UserProfile%\MobSF" /q /s >nul 2>&1
del /f "mobsf\setup_done.txt" >nul 2>&1
echo Deleting MobSF data directory: %mobsf_home%
del /f "%mobsf_home%" /q /s >nul 2>&1
rmdir "%mobsf_home%" /S /Q >nul 2>&1
echo Done
) ELSE (
echo Please run script from mobsf.MobSF directory
echo 'scripts/clean.bat y
)
@echo off
echo =======================MobSF Clean Script for Windows=======================
echo Running this script will delete the Scan database, all files uploaded and generated.
SET mobsf_home="%userprofile%\.MobSF"
SET mypath=%~dp0
echo %mypath:~0,-1%
IF "%~1"=="y" (
echo Deleting all uploads
rmdir "mobsf\uploads" /q /s >nul 2>&1
echo Deleting all downloads
rmdir "mobsf\downloads" /q /s >nul 2>&1
echo Deleting Static Analyzer migrations
rmdir "mobsf\StaticAnalyzer\migrations" /q /s >nul 2>&1
echo Deleting Dynamic Analyzer migrations
rmdir "mobsf\DynamicAnalyzer\migrations" /q /s >nul 2>&1
echo Deleting MobSF migrations
rmdir "mobsf\MobSF\migrations" /q /s >nul 2>&1
echo Deleting temp and log files
del /f "mobsf\debug.log" >nul 2>&1
del /f "classes*" >nul 2>&1
echo Deleting Scan database
del /f "mobsf\db.sqlite3" >nul 2>&1
echo Deleting Secret file
del /f "mobsf\secret" >nul 2>&1
echo Deleting Previous setup files
rmdir "%UserProfile%\MobSF" /q /s >nul 2>&1
del /f "mobsf\setup_done.txt" >nul 2>&1
echo Deleting MobSF data directory: %mobsf_home%
del /f "%mobsf_home%" /q /s >nul 2>&1
rmdir "%mobsf_home%" /S /Q >nul 2>&1
echo Done
) ELSE (
echo Please run script from mobsf.MobSF directory
echo 'scripts/clean.bat y
)
+36 -36
View File
@@ -1,47 +1,47 @@
#!/bin/bash
echo
echo '=======================MobSF Clean Script for Unix======================='
echo 'Running this script will delete the Scan database, all files uploaded and generated.'
echo 'Running this script will delete the scan database, all files uploaded and generated.'
script_path=$(dirname $0)
script_path=$(basename "$(dirname "$0")")
mobsf_home="$HOME/.MobSF"
if [ "$script_path" != "scripts" ] && [ "$script_path" != "./scripts" ]; then
echo 'Please run script from mobsf.MobSF directory '
echo './scripts/clean.sh '
exit 1
# Ensure the script is run from the correct directory
if [[ "$script_path" != "scripts" ]]; then
echo 'Please run this script from the MobSF directory:'
echo './scripts/clean.sh'
exit 1
fi
if [ "$1" != "" ]; then
VAL="$1"
else
read -p 'Continue? (Y/N): ' confirm && [[ $confirm == [yY] || $confirm == [yY][eE][sS] ]] || exit 1
# Confirmation prompt
VAL=${1:-}
if [[ -z "$VAL" ]]; then
read -p 'Continue? (Y/N): ' confirm
[[ $confirm =~ ^[yY]([eE][sS])?$ ]] || exit 1
VAL=$confirm
fi
echo
if [[ $VAL =~ ^[Yy]$ ]]
then
echo 'Deleting all uploads'
rm -rf ./mobsf/uploads/*
echo 'Deleting all downloads'
rm -rf ./mobsf/downloads/*
echo 'Deleting Static Analyzer migrations'
rm -rf ./mobsf/StaticAnalyzer/migrations/*
echo 'Deleting Dynamic Analyzer migrations'
rm -rf ./mobsf/DynamicAnalyzer/migrations/*
echo 'Deleting MobSF migrations'
rm -rf ./mobsf/MobSF/migrations/*
echo 'Deleting Python byte code files'
find ./ -name "*.pyc" -exec rm -rf {} \;
find ./ | grep -E "(__pycache__|\.pyo$)" | xargs rm -rf
echo 'Deleting temp and log files'
rm -rf ./mobsf/debug.log
rm -rf ./classes*
echo 'Deleting Scan database'
rm -rf ./mobsf/db.sqlite3
echo 'Deleting Secret file'
rm -rf ./mobsf/secret
echo "Deleting MobSF data directory: $mobsf_home"
rm -rf $mobsf_home
echo 'Done'
echo
if [[ "$VAL" =~ ^[yY]$ ]]; then
echo 'Cleaning up MobSF directories and files...'
# Remove files from key directories
rm -rf ./mobsf/{uploads,downloads,StaticAnalyzer/migrations,DynamicAnalyzer/migrations,MobSF/migrations}/*
echo 'Removing Python bytecode and cache files'
find ./ -type f -name "*.pyc" -o -name "*.pyo" -delete
find ./ -type d -name "__pycache__" -exec rm -rf {} +
# Remove temporary, log, and database files
echo 'Deleting temporary, log, and database files'
rm -f ./mobsf/debug.log ./classes* ./mobsf/db.sqlite3 ./mobsf/secret
# Remove the MobSF data directory if it exists
if [[ -d "$mobsf_home" ]]; then
echo "Deleting MobSF data directory: $mobsf_home"
rm -rf "$mobsf_home"
fi
echo 'Cleanup complete.'
fi
+55
View File
@@ -0,0 +1,55 @@
# Check if AVD_NAME and START_PORT are provided as arguments
param (
[string]$AVD_NAME,
[string]$START_PORT = "5554"
)
# Determine the emulator path based on Windows Android SDK location
$EMULATOR_PATH = "$env:LOCALAPPDATA\Android\Sdk\emulator\emulator.exe"
if (!(Test-Path $EMULATOR_PATH)) {
Write-Output "Emulator not found at $EMULATOR_PATH"
exit 1
}
# Locate adb path
$ADB_PATH = "$env:LOCALAPPDATA\Android\Sdk\platform-tools\adb.exe"
if (!(Test-Path $ADB_PATH)) {
$ADB_PATH = (where adb | Select-Object -First 1).ToString().Trim()
}
# Check if adb is available
if (!(Test-Path $ADB_PATH)) {
Write-Output "adb not found in common locations. Defaulting to 'adb' in PATH."
$ADB_PATH = "adb"
}
# If no AVD_NAME is provided, list available AVDs and exit
if (-not $AVD_NAME) {
Write-Output "Available AVDs:"
& "$EMULATOR_PATH" -list-avds
Write-Output "Use any Android AVD 5.0 - 11, up to API 30 without Google Play (production image)."
Write-Output "Usage: .\script.ps1 -AVD_NAME <AVD_NAME> [-START_PORT <START_PORT>]"
Write-Output "Example: .\script.ps1 -AVD_NAME Pixel_6_Pro_API_28 -START_PORT 5554"
exit 1
}
# Check if provided AVD_NAME exists in available AVDs
$AVD_FOUND = $false
$AVAILABLE_AVDS = & "$EMULATOR_PATH" -list-avds
foreach ($avd in $AVAILABLE_AVDS) {
if ($avd -eq $AVD_NAME) {
$AVD_FOUND = $true
break
}
}
if (-not $AVD_FOUND) {
Write-Output "Error: AVD $AVD_NAME not found in available AVDs."
Write-Output "Available AVDs:"
Write-Output $AVAILABLE_AVDS
exit 1
}
# Start the emulator with user-defined AVD and port
Start-Process -FilePath $EMULATOR_PATH -ArgumentList "-avd $AVD_NAME -writable-system -no-snapshot -wipe-data -port $START_PORT"
Write-Output "Emulator started with AVD $AVD_NAME on port $START_PORT."
+142
View File
@@ -0,0 +1,142 @@
#!/bin/bash
# Check if START_PORT, AVD_NAME, and open_gapps.zip are provided as arguments
AVD_NAME=$1
START_PORT=${2:-5554}
GAPPS_ZIP=$3
# Determine the emulator path based on OS
if [ "$(uname)" = "Darwin" ]; then
EMULATOR_PATH="$HOME/Library/Android/sdk/emulator/emulator"
elif [ "$(uname)" = "Linux" ]; then
EMULATOR_PATH="$HOME/Android/Sdk/emulator/emulator"
else
echo "$(tput setaf 1)Unsupported OS: $(uname)$(tput sgr0)"
exit 1
fi
# Check if the emulator path exists and is executable
if [ ! -x "$EMULATOR_PATH" ]; then
echo "$(tput setaf 1)Emulator not found at $EMULATOR_PATH$(tput sgr0)"
exit 1
fi
# Locate adb path
if [ -x "$HOME/Android/Sdk/platform-tools/adb" ]; then
ADB_PATH="$HOME/Android/Sdk/platform-tools/adb"
elif [ -x "$HOME/Library/Android/sdk/platform-tools/adb" ]; then
ADB_PATH="$HOME/Library/Android/sdk/platform-tools/adb"
elif command -v adb >/dev/null 2>&1; then
ADB_PATH=$(command -v adb)
else
echo "$(tput setaf 3)adb not found in common locations. Defaulting to 'adb' in PATH.$(tput sgr0)"
ADB_PATH="adb"
fi
# Check if adb is available
if [ ! -x "$ADB_PATH" ]; then
echo "$(tput setaf 1)adb not found at $ADB_PATH$(tput sgr0)"
exit 1
fi
# If no AVD_NAME is provided, list available AVDs and exit
if [ -z "$AVD_NAME" ]; then
echo -e "$(tput bold)Available AVDs:$(tput sgr0)\n"
"$EMULATOR_PATH" -list-avds
echo -e "$(tput bold)\nUse any Android AVD 5.0 - 11.0, up to API 30 without Google Play (production image).$(tput sgr0)"
echo "$(tput bold)Usage: $0 AVD_NAME [START_PORT] [open_gapps.zip path]$(tput sgr0)"
echo "$(tput bold)Example: $0 Pixel_6_Pro_API_28 5554 /path/to/open_gapps.zip$(tput sgr0)"
exit 1
fi
# Check if provided AVD_NAME exists in available AVDs
AVAILABLE_AVDS=$("$EMULATOR_PATH" -list-avds)
if ! echo "$AVAILABLE_AVDS" | grep -q "^$AVD_NAME$"; then
echo "$(tput setaf 1)Error: AVD $AVD_NAME not found in available AVDs.$(tput sgr0)"
echo "$(tput bold)Available AVDs:$(tput sgr0)"
echo "$AVAILABLE_AVDS"
exit 1
fi
# Kill any existing emulator processes
for pid in $(pgrep -f emulator); do
echo "Killing emulator process with PID $pid"
kill -9 "$pid"
done
# Start the emulator with user-defined AVD and port
"$EMULATOR_PATH" -avd "$AVD_NAME" -writable-system -no-snapshot -wipe-data -port "$START_PORT" >/dev/null 2>&1 &
echo "$(tput setaf 2)Emulator AVD $AVD_NAME started on port $START_PORT$(tput sgr0)"
# Check if socat is available only on Linux
if [ "$(uname)" = "Linux" ]; then
if command -v socat >/dev/null; then
SOCAT_AVAILABLE=true
else
SOCAT_AVAILABLE=false
echo "$(tput setaf 3)Warning: socat is not installed. Skipping port forwarding with socat. This might be required for docker in Linux.$(tput sgr0)"
fi
else
SOCAT_AVAILABLE=false
fi
# Increment ports and start socat listeners if socat is available
if [ "$SOCAT_AVAILABLE" = true ]; then
LISTEN_PORT=$((START_PORT + 2))
TARGET_PORT=$((START_PORT + 1))
# Remove all previous forwards
for pid in $(lsof -t -i TCP:$LISTEN_PORT -sTCP:LISTEN -c socat); do
echo "Killing socat process on port $LISTEN_PORT with PID $pid"
kill -9 "$pid"
done
# Start a single socat listener
socat TCP-LISTEN:$LISTEN_PORT,fork,reuseaddr TCP:localhost:$TARGET_PORT &
echo "socat listener started on port $LISTEN_PORT forwarding to $TARGET_PORT in the host."
echo "$(tput bold)Docker users please set the environment variable MOBSF_ANALYZER_IDENTIFIER=host.docker.internal:$LISTEN_PORT for adb connectivity.$(tput sgr0)"
fi
# Install Play Store if open_gapps.zip is provided
if [ -n "$GAPPS_ZIP" ]; then
if [ ! -f "$GAPPS_ZIP" ]; then
echo "$(tput setaf 1)Error: File $GAPPS_ZIP not found.$(tput sgr0)"
exit 1
fi
echo "Installing PlayStore"
if ! command -v unzip >/dev/null; then
echo "$(tput setaf 1)Error: unzip is not installed.$(tput sgr0)"
exit 1
fi
if ! command -v lzip >/dev/null; then
echo "$(tput setaf 1)Error: lzip is not installed.$(tput sgr0)"
exit 1
fi
PLAY_EXTRACT_DIR="play"
[ -d "$PLAY_EXTRACT_DIR" ] && rm -rf $PLAY_EXTRACT_DIR
unzip "$GAPPS_ZIP" 'Core/*' -d ./$PLAY_EXTRACT_DIR || { echo "$(tput setaf 1)Error: Unzip failed$(tput sgr0)"; exit 1; }
rm $PLAY_EXTRACT_DIR/Core/setup*
lzip -d $PLAY_EXTRACT_DIR/Core/*.lz || { echo "$(tput setaf 1)Error: Decompression failed$(tput sgr0)"; exit 1; }
for f in $(ls $PLAY_EXTRACT_DIR/Core/*.tar); do
tar -x --strip-components 2 -f $f -C $PLAY_EXTRACT_DIR || { echo "$(tput setaf 1)Error: Extraction failed$(tput sgr0)"; exit 1; }
done
echo "Waiting for emulator to complete booting..."
sleep 25
echo "Installing PlayStore components"
"$ADB_PATH" root
"$ADB_PATH" remount >/dev/null 2>&1
"$ADB_PATH" push $PLAY_EXTRACT_DIR/etc /system
"$ADB_PATH" push $PLAY_EXTRACT_DIR/framework /system
"$ADB_PATH" push $PLAY_EXTRACT_DIR/app /system
"$ADB_PATH" push $PLAY_EXTRACT_DIR/priv-app /system
"$ADB_PATH" shell stop
"$ADB_PATH" shell start
[ -d "$PLAY_EXTRACT_DIR" ] && rm -rf $PLAY_EXTRACT_DIR
echo "PlayStore installed successfully"
else
echo "$(tput setaf 3)No open_gapps.zip provided. Skipping Play Store installation.$(tput sgr0)"
fi
+79 -79
View File
@@ -1,79 +1,79 @@
@echo off
rem Python Check
set /a count=0
where python >nul 2>&1 && (
echo [INSTALL] Checking for Python version 3.10+
:redo
if %count% lss 3 (
set /a count+=1
rem Python Version Check
for /F "tokens=* USEBACKQ" %%F IN (`python --version`) DO (
set var=%%F
)
) else (
exit /b
)
echo %var%|findstr /R "[3].[101112]" >nul
if errorlevel 1 (
if "%var%"=="" goto redo
echo [ERROR] MobSF dependencies require Python 3.10-3.12. Your python points to %var%
exit /b
) else (
echo [INSTALL] Found %var%
)
rem Pip Check and Upgrade
pip >nul 2>&1 && (
echo [INSTALL] Found pip
python -m pip install --no-cache-dir --upgrade pip
) || (
echo [ERROR] pip is not available in PATH
pause
exit /b
)
rem OpenSSL Check
if exist "C:\\Program Files\\OpenSSL-Win64\\bin\\openssl.exe" (
echo [INSTALL] Found OpenSSL executable
) else (
echo [ERROR] OpenSSL executable not found in [C:\\Program Files\\OpenSSL-Win64\\bin\\openssl.exe]
echo [INFO] Install OpenSSL non-light version [Win64 OpenSSL v3.x] - https://slproweb.com/products/Win32OpenSSL.html
pause
exit /b
)
rem Visual Studio Build Tools Check
if exist "C:\\Program Files (x86)\\Microsoft Visual Studio" (
echo [INSTALL] Found Visual Studio Build Tools
) else (
echo [ERROR] Microsoft Visual C++ 14.0 not found in [C:\\Program Files (x86^)\\Microsoft Visual Studio]
echo [INFO] Install Microsoft Visual Studio Build Tools - https://visualstudio.microsoft.com/thank-you-downloading-visual-studio/?sku=BuildTools^&rel=16
pause
exit /b
)
set LIB=C:\Program Files\OpenSSL-Win64\lib;%LIB%
set INCLUDE=C:\Program Files\OpenSSL-Win64\include;%INCLUDE%
echo [INSTALL] Installing Requirements
python -m pip install --no-cache-dir wheel poetry==1.8.4
python -m poetry lock
python -m poetry install --only main --no-root --no-interaction --no-ansi || python -m poetry install --only main --no-root --no-interaction --no-ansi || python -m poetry install --only main --no-root --no-interaction --no-ansi
echo [INSTALL] Clean Up
call scripts/clean.bat y
echo [INSTALL] Migrating Database
set DJANGO_SUPERUSER_USERNAME=mobsf
set DJANGO_SUPERUSER_PASSWORD=mobsf
poetry run python manage.py makemigrations
poetry run python manage.py makemigrations StaticAnalyzer
poetry run python manage.py migrate
poetry run python manage.py createsuperuser --noinput --email ""
poetry run python manage.py create_roles
echo Download and Install wkhtmltopdf for PDF Report Generation - https://wkhtmltopdf.org/downloads.html
echo [INSTALL] Installation Complete
exit /b 0
) || (
echo [ERROR] python3 is not installed
)
@echo off
rem Python Check
set /a count=0
where python >nul 2>&1 && (
echo [INSTALL] Checking for Python version 3.10+
:redo
if %count% lss 3 (
set /a count+=1
rem Python Version Check
for /F "tokens=* USEBACKQ" %%F IN (`python --version`) DO (
set var=%%F
)
) else (
exit /b
)
echo %var%|findstr /R "[3].[101112]" >nul
if errorlevel 1 (
if "%var%"=="" goto redo
echo [ERROR] MobSF dependencies require Python 3.10-3.12. Your python points to %var%
exit /b
) else (
echo [INSTALL] Found %var%
)
rem Pip Check and Upgrade
pip >nul 2>&1 && (
echo [INSTALL] Found pip
python -m pip install --no-cache-dir --upgrade pip
) || (
echo [ERROR] pip is not available in PATH
pause
exit /b
)
rem OpenSSL Check
if exist "C:\\Program Files\\OpenSSL-Win64\\bin\\openssl.exe" (
echo [INSTALL] Found OpenSSL executable
) else (
echo [ERROR] OpenSSL executable not found in [C:\\Program Files\\OpenSSL-Win64\\bin\\openssl.exe]
echo [INFO] Install OpenSSL non-light version [Win64 OpenSSL v3.x] - https://slproweb.com/products/Win32OpenSSL.html
pause
exit /b
)
rem Visual Studio Build Tools Check
if exist "C:\\Program Files (x86)\\Microsoft Visual Studio" (
echo [INSTALL] Found Visual Studio Build Tools
) else (
echo [ERROR] Microsoft Visual C++ 14.0 not found in [C:\\Program Files (x86^)\\Microsoft Visual Studio]
echo [INFO] Install Microsoft Visual Studio Build Tools - https://visualstudio.microsoft.com/thank-you-downloading-visual-studio/?sku=BuildTools^&rel=16
pause
exit /b
)
set LIB=C:\Program Files\OpenSSL-Win64\lib;%LIB%
set INCLUDE=C:\Program Files\OpenSSL-Win64\include;%INCLUDE%
echo [INSTALL] Installing Requirements
python -m pip install --no-cache-dir wheel poetry==1.8.4
python -m poetry lock
python -m poetry install --only main --no-root --no-interaction --no-ansi || python -m poetry install --only main --no-root --no-interaction --no-ansi || python -m poetry install --only main --no-root --no-interaction --no-ansi
echo [INSTALL] Clean Up
call scripts/clean.bat y
echo [INSTALL] Migrating Database
set DJANGO_SUPERUSER_USERNAME=mobsf
set DJANGO_SUPERUSER_PASSWORD=mobsf
poetry run python manage.py makemigrations
poetry run python manage.py makemigrations StaticAnalyzer
poetry run python manage.py migrate
poetry run python manage.py createsuperuser --noinput --email ""
poetry run python manage.py create_roles
echo Download and Install wkhtmltopdf for PDF Report Generation - https://wkhtmltopdf.org/downloads.html
echo [INSTALL] Installation Complete
exit /b 0
) || (
echo [ERROR] python3 is not installed
)
+27 -31
View File
@@ -1,50 +1,43 @@
#!/bin/bash
# Python3 Check
unamestr=$(uname)
if ! [ -x "$(command -v python3)" ]; then
# Check for Python3 and validate version
if ! command -v python3 &>/dev/null; then
echo '[ERROR] python3 is not installed.' >&2
exit 1
fi
# Python3 Version Check
python_version="$(python3 --version 2>&1 | awk '{print $2}')"
py_major=$(echo "$python_version" | cut -d'.' -f1)
py_minor=$(echo "$python_version" | cut -d'.' -f2)
if [ "$py_major" -eq "3" ] && [ "$py_minor" -gt "9" ] && [ "$py_minor" -lt "13" ]; then
echo "[INSTALL] Found Python ${python_version}"
else
echo "[ERROR] MobSF dependencies require Python 3.10 - 3.12. You have Python version ${python_version} or python3 points to Python ${python_version}."
python_version=$(python3 --version 2>&1 | awk '{print $2}')
py_major=${python_version%%.*}
py_minor=${python_version#*.}
py_minor=${py_minor%%.*}
if [[ "$py_major" -ne 3 || "$py_minor" -lt 10 || "$py_minor" -gt 12 ]]; then
echo "[ERROR] MobSF dependencies require Python 3.10 - 3.12. You have Python ${python_version}."
exit 1
fi
echo "[INSTALL] Found Python ${python_version}"
# Pip Check and Upgrade
python3 -m pip -V
if [ $? -eq 0 ]; then
# Check and upgrade pip
if python3 -m pip -V &>/dev/null; then
echo '[INSTALL] Found pip'
if [[ $unamestr == 'Darwin' ]]; then
python3 -m pip install --no-cache-dir --upgrade pip
else
python3 -m pip install --no-cache-dir --upgrade pip --user
fi
upgrade_cmd="python3 -m pip install --no-cache-dir --upgrade pip"
[[ "$(uname)" != "Darwin" ]] && upgrade_cmd+=" --user"
eval $upgrade_cmd
else
echo '[ERROR] python3-pip not installed'
exit 1
fi
# macOS Specific Checks
if [[ $unamestr == 'Darwin' ]]; then
# Check if xcode is installed
xcode-select -v
if ! [ $? -eq 0 ]; then
echo 'Please install command-line tools'
echo 'xcode-select --install'
# macOS-specific Xcode CLI tools check
if [[ "$(uname)" == "Darwin" ]]; then
if ! xcode-select -v &>/dev/null; then
echo 'Please install command-line tools with: xcode-select --install'
exit 1
else
echo '[INSTALL] Found Xcode'
fi
fi
echo '[INSTALL] Found Xcode'
fi
# Install dependencies and set up the environment
echo '[INSTALL] Installing Requirements'
python3 -m pip install --no-cache-dir wheel poetry==1.8.4
python3 -m poetry lock
@@ -53,6 +46,7 @@ python3 -m poetry install --no-root --only main --no-interaction --no-ansi
echo '[INSTALL] Clean Up'
bash scripts/clean.sh y
# Database setup and superuser creation
echo '[INSTALL] Migrating Database'
export DJANGO_SUPERUSER_USERNAME=mobsf
export DJANGO_SUPERUSER_PASSWORD=mobsf
@@ -61,8 +55,10 @@ python3 -m poetry run python manage.py makemigrations StaticAnalyzer
python3 -m poetry run python manage.py migrate
python3 -m poetry run python manage.py createsuperuser --noinput --email ""
python3 -m poetry run python manage.py create_roles
wkhtmltopdf -V
if ! [ $? -eq 0 ]; then
# Check for wkhtmltopdf
if ! command -v wkhtmltopdf &>/dev/null; then
echo 'Download and Install wkhtmltopdf for PDF Report Generation - https://wkhtmltopdf.org/downloads.html'
fi
echo '[INSTALL] Installation Complete'