Compare commits

...

5 Commits

Author SHA1 Message Date
Nikolaos Tosis ef5cc5b579
Merge 75f956de0b into da743a2878 2024-02-13 15:31:38 +09:00
github-actions[bot] da743a2878
Add new iOS versions and build numbers (#460)
Co-authored-by: DonnchaC <DonnchaC@users.noreply.github.com>
2024-02-09 15:17:53 +01:00
Rory Flynn 4681b57adc
Handle no indicators provided in `sms_attachments.py` (#455)
* Handle no indicators provided in `sms_attachments.py`

* Move guard to a more specific place

* Unrelated black formatting

* Related black changes :)
2024-02-07 13:30:27 +01:00
Rory Flynn bb7a22ed0b
Update install docs (#449) 2024-02-05 14:17:40 +01:00
Nikolaos Tosis 75f956de0b
Create ios_GUI.py
initial version
2022-09-18 16:58:25 +02:00
5 changed files with 249 additions and 15 deletions

View File

@ -7,11 +7,27 @@ Before proceeding, please note that MVT requires Python 3.6+ to run. While it sh
First install some basic dependencies that will be necessary to build all required tools:
```bash
sudo apt install python3 python3-pip libusb-1.0-0 sqlite3
sudo apt install python3 python3-venv python3-pip sqlite3 libusb-1.0-0
```
*libusb-1.0-0* is not required if you intend to only use `mvt-ios` and not `mvt-android`.
(Recommended) Set up `pipx`
For Ubuntu 23.04 or above:
```bash
sudo apt install pipx
pipx ensurepath
```
For Ubuntu 22.04 or below:
```
python3 -m pip install --user pipx
python3 -m pipx ensurepath
```
Other distributions: check for a `pipx` or `python-pipx` via your package manager.
When working with Android devices you should additionally install [Android SDK Platform Tools](https://developer.android.com/studio/releases/platform-tools). If you prefer to install a package made available by your distribution of choice, please make sure the version is recent to ensure compatibility with modern Android devices.
## Dependencies on macOS
@ -21,7 +37,7 @@ Running MVT on macOS requires Xcode and [homebrew](https://brew.sh) to be instal
In order to install dependencies use:
```bash
brew install python3 libusb sqlite3
brew install python3 pipx libusb sqlite3
```
*libusb* is not required if you intend to only use `mvt-ios` and not `mvt-android`.
@ -42,24 +58,43 @@ It is recommended to try installing and running MVT from [Windows Subsystem Linu
## Installing MVT
If you haven't done so, you can add this to your `.bashrc` or `.zshrc` file in order to add locally installed PyPI binaries to your `$PATH`:
### Installing from PyPI with pipx (recommended)
1. Install `pipx` following the instructions above for your OS/distribution. Make sure to run `pipx ensurepath` and open a new terminal window.
2. ```bash
pipx install mvt
```
You now should have the `mvt-ios` and `mvt-android` utilities installed. If you run into problems with these commands not being found, ensure you have run `pipx ensurepath` and opened a new terminal window.
### Installing from PyPI directly into a virtual environment
You can use `pipenv`, `poetry` etc. for your virtual environment, but the provided example is with the built-in `venv` tool:
1. Create the virtual environment in a folder in the current directory named `env`:
```bash
export PATH=$PATH:~/.local/bin
python3 -m venv env
```
Then you can install MVT directly from [PyPI](https://pypi.org/project/mvt/)
2. Activate the virtual environment:
```bash
pip3 install mvt
source env/bin/activate
```
If you want to have the latest features in development, you can install MVT directly from the source code. If you installed MVT previously from pypi, you should first uninstall it using `pip3 uninstall mvt` and then install from the source code:
3. Install `mvt` into the virtual environment:
```bash
pip install mvt
```
The `mvt-ios` and `mvt-android` utilities should now be available as commands whenever the virtual environment is active.
### Installing from git source with pipx
If you want to have the latest features in development, you can install MVT directly from the source code in git.
```bash
git clone https://github.com/mvt-project/mvt.git
cd mvt
pip3 install .
pipx install --force git+https://github.com/mvt-project/mvt.git
```
You now should have the `mvt-ios` and `mvt-android` utilities installed.
**Notes:**
1. The `--force` flag is necessary to force the reinstallation of the package.
2. To revert to using a PyPI version, it will be necessary to `pipx uninstall mvt` first.

193
gui/ios_GUI.py Normal file
View File

@ -0,0 +1,193 @@
from tkinter import *
from tkinter.ttk import Treeview,Combobox,Style
from tkinter import filedialog,messagebox
import pip._internal as pip
import platform
import sys,os
import logging,requests
from rich.logging import RichHandler
#mvt module imports, if not exit install it
try:
from mvt.ios.decrypt import DecryptBackup
from mvt.ios.modules.backup import BACKUP_MODULES
from mvt.ios.modules.fs import FS_MODULES
from mvt.ios.modules.mixed import MIXED_MODULES
from mvt.common.module import run_module,save_timeline
from mvt.common.indicators import Indicators, IndicatorsFileBadFormat
except ImportError:
pip.main(['install', 'mvt'])
from mvt.ios.decrypt import DecryptBackup
from mvt.ios.modules.backup import BACKUP_MODULES
from mvt.ios.modules.fs import FS_MODULES
from mvt.ios.modules.mixed import MIXED_MODULES
from mvt.common.indicators import Indicators, IndicatorsFileBadFormat
from mvt.common.module import run_module,save_timeline
# Setup logging using Rich.
LOG_FORMAT = "[%(name)s] %(message)s"
logging.basicConfig(level="INFO", format=LOG_FORMAT, handlers=[
RichHandler(show_path=False, log_time_format="%X")])
log = logging.getLogger(__name__)
# If is windows, use the default path as default
backupFolder:str =''
if platform.system()=='Windows':
backupFolder = os.path.expanduser('~\Apple') + '\MobileSync\Backup'
elif platform.system()=='Darwin':
backupFolder = 'C:\\'
else:
sys.exit("Operating system is not compatible")
#use the correct slashes according to OS
decryptedFolder:str =''
resultsFolder:str =''
if platform.system()=='Windows':
decryptedFolder = 'C:/'
elif platform.system()=='Darwin':
decryptedFolder = 'C:\\'
else:
sys.exit("Operating system is not compatible")
#function to download automatic the STIX files
def dowload_STIX(output):
pegasus = 'https://raw.githubusercontent.com/AmnestyTech/investigations/master/2021-07-18_nso/pegasus.stix2'
predator = 'https://raw.githubusercontent.com/AmnestyTech/investigations/master/2021-12-16_cytrox/cytrox.stix2'
r1 = requests.get(pegasus, allow_redirects=False)
r2 = requests.get(predator, allow_redirects=False)
h = open(output + 'pegasus.stix2', 'wb').write(r1.content)
h = open(output +'cytrox.stix2', 'wb').write(r2.content)
return [output + 'pegasus.stix2',output +'cytrox.stix2']
def browseFileAction(event,obj, id):
global backupFolder,decryptedFolder,resultsFolder
searchPathDirectory = filedialog.askdirectory(title="select", initialdir=backupFolder)
#update the path in the label's text
obj["text"] = searchPathDirectory
#update the #Global variable
if id=="INPUT":
backupFolder = searchPathDirectory
else :
#set output and results folder
decryptedFolder = searchPathDirectory
if platform.system()=='Windows':
resultsFolder = decryptedFolder + '/Results/'
elif platform.system()=='Darwin':
resultsFolder = decryptedFolder + '\Results\\'
else:
sys.exit("Operating system is not compatible")
#use underscore to avoid conflict
def check_backup__(output, backup_path,iocs):
log.info("Checking iTunes backup located at: %s", backup_path)
if output and not os.path.exists(output):
try:
os.makedirs(output)
except Exception as e:
log.critical("Unable to create output folder %s: %s", output, e)
os.exit(1)
indicators = Indicators(log=log)
for ioc_path in iocs:
try:
indicators.parse_stix2(ioc_path)
except IndicatorsFileBadFormat as e:
log.critical(e)
os.exit(1)
log.info("Loaded a total of %d indicators", indicators.ioc_count)
timeline = []
timeline_detected = []
for backup_module in BACKUP_MODULES + MIXED_MODULES:
m = backup_module(base_folder=backup_path, output_folder=output, fast_mode=False,
log=logging.getLogger(backup_module.__module__))
m.is_backup = True
if iocs:
m.indicators = indicators
m.indicators.log = m.log
run_module(m)
timeline.extend(m.timeline)
timeline_detected.extend(m.timeline_detected)
if output:
if len(timeline) > 0:
save_timeline(timeline, os.path.join(output, "timeline.csv"))
if len(timeline_detected) > 0:
save_timeline(timeline_detected, os.path.join(output, "timeline_detected.csv"))
log.info("Checking completed")
def run(event,arg, id):
global backupFolder,decryptedFolder,resultsFolder
password = arg.get()
if len(password)==0:
messagebox.showerror("Password required", "Please enter first your backup password.")
return
backup = DecryptBackup(backupFolder, decryptedFolder)
backup.decrypt_with_password(password)
#start decryption
backup.process_backup()
l = dowload_STIX(resultsFolder)
#check the stored links against the STIX
check_backup__(resultsFolder,decryptedFolder,l)
app = Tk()
#Create first frame for some infos
frameInfo = LabelFrame(app, text="Info",pady=5)
frameInfo.grid(row=0, column=0,padx=5,sticky=W)
lblRootFolder = Label(frameInfo, text='Select backup folder: ',
font=('normal', 11),padx=10)
lblRootFolder.grid(row=0, column=0)
lblRootFolderName = Label(frameInfo, text=backupFolder,
font=('normal', 11),width=40,wraplength=280)
lblRootFolderName.grid(row=0, column=1)
browseButton = Button(frameInfo, text = 'Browse', width = 14)
browseButton.grid(row=0, column=2,pady=4)
outputFolder = Button(frameInfo, text='Browse', width=14)
outputFolder.grid(row=1, column=2,padx=4)
lblSessionStatus = Label(frameInfo, text='Browse decrypted path: ',
font=('normal', 11))
lblSessionStatus.grid(row=1, column=0,padx=10)
lblSessionStatusMessage = Label(frameInfo, text=decryptedFolder,
font=('normal', 11),width=40,wraplength=280)
lblSessionStatusMessage.grid(row=1, column=1)
labelEnterPassword = Label(frameInfo, text='Enter your backup password: ',
font=('normal', 11),padx=10)
labelEnterPassword.grid(row=3, column=0)
passwordEnrty = Entry(frameInfo, show="*", width=15)
passwordEnrty.grid(row=3, column=2,padx=4)
runButton = Button(frameInfo,text='Run analysis', width=14)
runButton.grid(row=4, column=0,padx=4)
# Create bind
#connect browse button with the action function.
browseButton.bind("<ButtonRelease-1>",lambda event, objToLabel=lblRootFolderName: browseFileAction(event,objToLabel, 'INPUT') )
outputFolder.bind("<ButtonRelease-1>",lambda event, objToLabel=lblSessionStatusMessage: browseFileAction(event,objToLabel, 'OUTPUT') )
runButton.bind("<ButtonRelease-1>",lambda event, objToLabel=passwordEnrty: run(event,objToLabel, 'buttonRelease1') )
#Create and call main window
app.title('Predator/Pegasus iOS scanner GUI')
app.geometry('720x150')
# Add Some Style
style = Style()
# Pick A Theme
style.theme_use('default')
# Main window
#add some action before closing window.
def on_closing():
app.destroy()
app.protocol("WM_DELETE_WINDOW",on_closing)
# Start program
app.mainloop()

View File

@ -1027,5 +1027,9 @@
{
"version": "17.3",
"build": "21D50"
},
{
"version": "17.3.1",
"build": "21D61"
}
]

View File

@ -69,9 +69,9 @@ class Calls(IOSExtraction):
"isodate": convert_mactime_to_iso(row[0]),
"duration": row[1],
"location": row[2],
"number": row[3].decode("utf-8")
if row[3] and row[3] is bytes
else row[3],
"number": (
row[3].decode("utf-8") if row[3] and row[3] is bytes else row[3]
),
"provider": row[4],
}
)

View File

@ -56,7 +56,9 @@ class SMSAttachments(IOSExtraction):
def check_indicators(self) -> None:
for attachment in self.results:
# Check for known malicious filenames.
if self.indicators.check_file_path(attachment["filename"]):
if self.indicators and self.indicators.check_file_path(
attachment["filename"]
):
self.detected.append(attachment)
if (