Skip to content

Commit

Permalink
Merge branch 'master' into swift-macho-update
Browse files Browse the repository at this point in the history
  • Loading branch information
ajinabraham authored Dec 6, 2023
2 parents a6c9f08 + 361e76a commit b986080
Show file tree
Hide file tree
Showing 180 changed files with 14,160 additions and 1,891 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/mobsf-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ jobs:
fail-fast: false
matrix:
os: [ubuntu-22.04, macos-latest, windows-latest]
python-version: [3.9, '3.10', '3.11']
python-version: ['3.10', '3.11']

runs-on: ${{ matrix.os }}
steps:
Expand Down
27 changes: 0 additions & 27 deletions .pyup.yml

This file was deleted.

2 changes: 1 addition & 1 deletion .sonarcloud.properties
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
sonar.sources=.
sonar.exclusions=mobsf/static/**/*,mobsf/templates/**/*
sonar.sourceEncoding=UTF-8
sonar.python.version=3.7, 3.8, 3.9, 3.10, 3.11
sonar.python.version=3.10, 3.11
4 changes: 3 additions & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,10 @@ RUN apt update -y && apt install -y --no-install-recommends \
curl \
git \
jq \
unzip \
android-tools-adb && \
locale-gen en_US.UTF-8
locale-gen en_US.UTF-8 && \
apt upgrade -y

ENV MOBSF_USER=mobsf \
MOBSF_PLATFORM=docker \
Expand Down
5 changes: 2 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,20 +1,19 @@
# Mobile Security Framework (MobSF)
Version: v3.7 beta
Version: v3.8 beta

![](https://cloud.githubusercontent.com/assets/4301109/20019521/cc61f7fc-a2f2-11e6-95f3-407030d9fdde.png)

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. MobSF supports mobile app binaries (APK, XAPK, IPA & APPX) along with zipped source code and provides REST APIs for seamless integration with your CI/CD or DevSecOps pipeline.The Dynamic Analyzer helps you to perform runtime security assessment and interactive instrumented testing.

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.9+-blue.svg?logo=python&labelColor=yellow)](https://www.python.org/downloads/)
[![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)
[![Requirements Status](https://pyup.io/repos/github/MobSF/Mobile-Security-Framework-MobSF/shield.svg)](https://pyup.io/repos/github/MobSF/Mobile-Security-Framework-MobSF/)
[![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)
[![CII Best Practices](https://bestpractices.coreinfrastructure.org/projects/6392/badge)](https://bestpractices.coreinfrastructure.org/projects/6392)
Expand Down
6 changes: 6 additions & 0 deletions mobsf/DynamicAnalyzer/forms.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
"""File upload to iOS form."""
from django import forms


class UploadFileForm(forms.Form):
file = forms.FileField()
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,4 @@ Java.perform(function () {
}
return response;
}
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,198 @@
Java.perform(function () {
try {
// Bypass isDebuggerConnected() check
var Debug = Java.use('android.os.Debug');
Debug.isDebuggerConnected.implementation = function () {
send('[Debugger Check] isDebuggerConnected() check bypassed');
return false;
}
} catch(e){}
});
// Following are based on: https://github.com/apkunpacker/FridaScripts
try {
/* Bypass Frida Detection Based On Port Number */
Interceptor.attach(Module.findExportByName("libc.so", "connect"), {
onEnter: function(args) {
var memory = Memory.readByteArray(args[1], 64);
var b = new Uint8Array(memory);
if (b[2] == 0x69 && b[3] == 0xa2 && b[4] == 0x7f && b[5] == 0x00 && b[6] == 0x00 && b[7] == 0x01) {
this.frida_detection = true;
}
},
onLeave: function(retval) {
if (this.frida_detection) {
send("[Debugger Check] Frida Port detection bypassed");
retval.replace(-1);
}
}
});
} catch(e){}
try {
Interceptor.attach(Module.findExportByName(null, "connect"), {
onEnter: function(args) {
var family = Memory.readU16(args[1]);
if (family !== 2) {
return
}
var port = Memory.readU16(args[1].add(2));
port = ((port & 0xff) << 8) | (port >> 8);
if (port === 27042) {
send('[Debugger Check] Frida Port detection bypassed');
Memory.writeU16(args[1].add(2), 0x0101);
}
}
});
} catch(e){}
try {
/* Bypass TracerPid Detection Based On Pid Status */
var fgetsPtr = Module.findExportByName("libc.so", "fgets");
var fgets = new NativeFunction(fgetsPtr, 'pointer', ['pointer', 'int', 'pointer']);
Interceptor.replace(fgetsPtr, new NativeCallback(function(buffer, size, fp) {
var retval = fgets(buffer, size, fp);
var bufstr = Memory.readUtf8String(buffer);
if (bufstr.indexOf("TracerPid:") > -1) {
Memory.writeUtf8String(buffer, "TracerPid:\t0");
send("[Debugger Check] TracerPID check bypassed");
}
return retval;
}, 'pointer', ['pointer', 'int', 'pointer']))
} catch(e){}

try {
/* Bypass Ptrace Checks */
Interceptor.attach(Module.findExportByName(null, "ptrace"), {
onEnter: function(args) {},
onLeave: function(retval) {
send("[Debugger Check] Ptrace check bypassed");
retval.replace(0);
}
})
} catch(e){}

try {
/* Watch Child Process Forking */
var fork = Module.findExportByName(null, "fork")
Interceptor.attach(fork, {
onEnter: function(args) {},
onLeave: function(retval) {
var pid = parseInt(retval.toString(16), 16)
send("[Debugger Check] Hook fork child process PID: " + pid)
}
})
} catch(e){}


/* Xposed Detection Bypass */
Java.perform(function() {
try {
var cont = Java.use("java.lang.String");
cont.contains.overload("java.lang.CharSequence").implementation = function(checks) {
var check = checks.toString();
if (check.indexOf("libdexposed") >= 0 || check.indexOf("libsubstrate.so") >= 0 || check.indexOf("libepic.so") >= 0 || check.indexOf("libxposed") >= 0) {
var BypassCheck = "libpkmkb.so";
send("[Debugger Check] Xposed library check bypassed");
return this.contains.call(this, BypassCheck);
}
return this.contains.call(this, checks);
}
} catch (erro) {
console.error(erro);
}
try {
var StacktraceEle = Java.use("java.lang.StackTraceElement");
StacktraceEle.getClassName.overload().implementation = function() {
var Flag = false;
var ClazzName = this.getClassName();
if (ClazzName.indexOf("com.saurik.substrate.MS$2") >= 0 || ClazzName.indexOf("de.robv.android.xposed.XposedBridge") >= 0) {
send("[Debugger Check] Debugger detection check bypassed for class: " + this.getClassName());
Flag = true;
if (Flag) {
var StacktraceEle = Java.use("java.lang.StackTraceElement");
StacktraceEle.getClassName.overload().implementation = function() {
var gMN = this.getMethodName();
if (gMN.indexOf("handleHookedMethod") >= 0 || gMN.indexOf("invoked") >= 0) {
send("[Debugger Check] Debugger detection check bypassed for method: " + this.getMethodName());
return "bye.pass";
}
return this.getMethodName();
}
}
return "com.android.vending"
}
return this.getClassName();
}
} catch (errr) {
console.error(errr);
}
})
/* VPN Related Checks */
Java.perform(function() {
var NInterface = Java.use("java.net.NetworkInterface");
try {
var NInterface = Java.use("java.net.NetworkInterface");
NInterface.getName.overload().implementation = function() {
var IName = this.getName();
if (IName == "tun0" || IName == "ppp0" || IName == "p2p0" || IName == "ccmni0" || IName == "tun") {
send("[Debugger Check] Bypassed Network Interface name check: " + JSON.stringify(this.getName()));
return "Bypass";
}
return this.getName();
}
} catch (err) {
console.error(err);
}
// HTTP(s) Proxy check
try {
var GetProperty = Java.use("java.lang.System");
GetProperty.getProperty.overload("java.lang.String").implementation = function(getprop) {
if (getprop.indexOf("http.proxyHost") >= 0 || getprop.indexOf("http.proxyPort") >= 0) {
var newprop = "CKMKB"
send("[Debugger Check] HTTP(s) proxy check bypassed")
return this.getProperty.call(this, newprop);
}
return this.getProperty(getprop);
}
} catch (err) {
console.error(err);
}
// NetworkCapabilities check
try {
var NCap = Java.use("android.net.NetworkCapabilities");
NCap.hasTransport.overload("int").implementation = function(values) {
if (values == 4){
send("[Debugger Check] HasTransportcheck bypassed")
return false;
} else
return this.hasTransport(values);
}
} catch (e) {
console.error(e);
}
})
/* Developer Mod Check Bypass */
Java.perform(function() {
try{
var SSecure = Java.use("android.provider.Settings$Secure");
SSecure.getStringForUser.overload('android.content.ContentResolver', 'java.lang.String', 'int').implementation = function(Content, Name, Flag) {
if (Name.indexOf("development_settings_enabled") >= 0) {
send("[Debugger Check] Developer mode check bypassed for: " + Name)
return this.getStringForUser.call(this, Content, "bypassed", Flag);
}
return this.getStringForUser(Content, Name, Flag);
}
} catch(e){}
})

/* Playstore install source check */
Java.perform(function() {
try{
var Installer = Java.use("android.app.ApplicationPackageManager");
Installer.getInstallerPackageName.overload('java.lang.String').implementation = function(Str) {
var playPkg = "com.android.vending";
if (Str.toString().indexOf(playPkg) < 0) {
send("[Debugger Check] Play Store install source check bypassed. Original value: "+ Str.toString());
return playPkg;
}
}
} catch(e){}
})
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
// Based on https://github.com/sensepost/objection/blob/f8e78d8a29574c6dadd2b953a63207b45a19b1cf/objection/hooks/android/clipboard/monitor.js
var ActivityThread = Java.use('android.app.ActivityThread');
var ClipboardManager = Java.use('android.content.ClipboardManager');
var CLIPBOARD_SERVICE = 'clipboard';

var currentApplication = ActivityThread.currentApplication();
var context = currentApplication.getApplicationContext();

var clipboard_handle = context.getApplicationContext().getSystemService(CLIPBOARD_SERVICE);
var clipboard = Java.cast(clipboard_handle, ClipboardManager);

// Variable used for the current string data
var string_data;

function check_clipboard_data() {

Java.perform(function () {

var primary_clip = clipboard.getPrimaryClip();

// If we have managed to get the primary clipboard and there are
// items stored in it, process an update.
if (primary_clip != null && primary_clip.getItemCount() > 0) {

var data = primary_clip.getItemAt(0).coerceToText(context).toString();

// If the data is the same, just stop.
if (string_data == data) {
return;
}

// Update the data with the new string and report back.
string_data = data;
send('mobsf-android-clipboard:' + data);
}
});
}

// Poll every 5 seconds
setInterval(check_clipboard_data, 1000 * 5);
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,8 @@ Java.performNow(function () {
};

// String.contains check
var String = Java.use('java.lang.String');
String.contains.implementation = function (name) {
var javaString = Java.use('java.lang.String');
javaString.contains.implementation = function (name) {
if (name == "test-keys") {
send("[RootDetection Bypass] test-keys check");
return false;
Expand Down Expand Up @@ -130,12 +130,12 @@ Java.performNow(function () {
}
}
if (shouldModifyCommand) {
send("[RootDetection Bypass] ProcessBuilder " + cmd);
send("[RootDetection Bypass] ProcessBuilder " + JSON.stringify(cmd));
this.command.call(this, ["grep"]);
return this.start.call(this);
}
if (cmd.indexOf("su") != -1) {
send("[RootDetection Bypass] ProcessBuilder " + cmd);
send("[RootDetection Bypass] ProcessBuilder " + JSON.stringify(cmd));
this.command.call(this, ["justafakecommandthatcannotexistsusingthisshouldthowanexceptionwheneversuiscalled"]);
return this.start.call(this);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
// Based on https://github.com/sensepost/objection/blob/f8e78d8a29574c6dadd2b953a63207b45a19b1cf/objection/hooks/android/filesystem/environment.js
var ActivityThread = Java.use('android.app.ActivityThread');

var currentApplication = ActivityThread.currentApplication();
var context = currentApplication.getApplicationContext();

var data = {

filesDirectory: context.getFilesDir().getAbsolutePath().toString(),
cacheDirectory: context.getCacheDir().getAbsolutePath().toString(),
externalCacheDirectory: context.getExternalCacheDir().getAbsolutePath().toString(),
codeCacheDirectory: 'getCodeCacheDir' in context ? context.getCodeCacheDir().getAbsolutePath().toString() : 'n/a',
obbDir: context.getObbDir().getAbsolutePath().toString(),
packageCodePath: context.getPackageCodePath().toString()
};


send(JSON.stringify(data, null, 2));
Loading

0 comments on commit b986080

Please sign in to comment.