mirror of https://github.com/mvt-project/mvt.git
Compare commits
12 Commits
d1950064e0
...
85d7d96383
Author | SHA1 | Date |
---|---|---|
FORCHA PEARL | 85d7d96383 | |
Rory Flynn | cbd41b2aff | |
Rory Flynn | 0509eaa162 | |
Rory Flynn | 59e6dff1e1 | |
Rory Flynn | f1821d1a02 | |
Rory Flynn | 6c7ad0ac95 | |
tek | 3a997d30d2 | |
tek | 6f56939dd7 | |
Donncha Ó Cearbhaill | 7a4946e2c6 | |
r-tx | e1c4f4eb7a | |
Donncha Ó Cearbhaill | f9d7b550dc | |
FORCHA | 4b89887f4b |
|
@ -40,7 +40,9 @@ jobs:
|
|||
- name: Safety checks
|
||||
run: safety check
|
||||
- name: Test with pytest and coverage
|
||||
run: pytest --junitxml=pytest.xml --cov-report=term-missing:skip-covered --cov=mvt tests/ | tee pytest-coverage.txt
|
||||
run: |
|
||||
set -o pipefail
|
||||
pytest --junitxml=pytest.xml --cov-report=term-missing:skip-covered --cov=mvt tests/ | tee pytest-coverage.txt
|
||||
- name: Pytest coverage comment
|
||||
continue-on-error: true # Workflows running on a fork can't post comments
|
||||
uses: MishaKav/pytest-coverage-comment@main
|
||||
|
|
|
@ -13,7 +13,6 @@ ENV DEBIAN_FRONTEND=noninteractive
|
|||
# ----------------------------
|
||||
RUN apt update \
|
||||
&& apt install -y python3 python3-pip libusb-1.0-0-dev wget unzip default-jre-headless adb \
|
||||
|
||||
# Install build tools for libimobiledevice
|
||||
# ----------------------------------------
|
||||
build-essential \
|
||||
|
@ -27,7 +26,6 @@ RUN apt update \
|
|||
libssl-dev \
|
||||
sqlite3 \
|
||||
pkg-config \
|
||||
|
||||
# Clean up
|
||||
# --------
|
||||
&& apt-get clean \
|
||||
|
@ -41,17 +39,11 @@ RUN git clone https://github.com/libimobiledevice/libplist \
|
|||
&& git clone https://github.com/libimobiledevice/libusbmuxd \
|
||||
&& git clone https://github.com/libimobiledevice/libimobiledevice \
|
||||
&& git clone https://github.com/libimobiledevice/usbmuxd \
|
||||
|
||||
&& cd libplist && ./autogen.sh && make && make install && ldconfig \
|
||||
|
||||
&& cd ../libimobiledevice-glue && PKG_CONFIG_PATH=/usr/local/lib/pkgconfig ./autogen.sh --prefix=/usr && make && make install && ldconfig \
|
||||
|
||||
&& cd ../libusbmuxd && PKG_CONFIG_PATH=/usr/local/lib/pkgconfig ./autogen.sh && make && make install && ldconfig \
|
||||
|
||||
&& cd ../libimobiledevice && PKG_CONFIG_PATH=/usr/local/lib/pkgconfig ./autogen.sh --enable-debug && make && make install && ldconfig \
|
||||
|
||||
&& cd ../usbmuxd && PKG_CONFIG_PATH=/usr/local/lib/pkgconfig ./autogen.sh --prefix=/usr --sysconfdir=/etc --localstatedir=/var --runstatedir=/run && make && make install \
|
||||
|
||||
# Clean up.
|
||||
&& cd .. && rm -rf libplist libimobiledevice-glue libusbmuxd libimobiledevice usbmuxd
|
||||
|
||||
|
|
|
@ -26,7 +26,7 @@ MVT supports using public [indicators of compromise (IOCs)](https://github.com/m
|
|||
>
|
||||
> Reliable and comprehensive digital forensic support and triage requires access to non-public indicators, research and threat intelligence.
|
||||
>
|
||||
>Such support is available to civil society through [Amnesty International's Security Lab](https://www.amnesty.org/en/tech/) or through our forensic partnership with [Access Now’s Digital Security Helpline](https://www.accessnow.org/help/).
|
||||
>Such support is available to civil society through [Amnesty International's Security Lab](https://securitylab.amnesty.org/get-help/?c=mvt_docs) or through our forensic partnership with [Access Now’s Digital Security Helpline](https://www.accessnow.org/help/).
|
||||
|
||||
More information about using indicators of compromise with MVT is available in the [documentation](https://docs.mvt.re/en/latest/iocs/).
|
||||
|
||||
|
|
|
@ -21,7 +21,7 @@ MVT supports using [indicators of compromise (IOCs)](https://github.com/mvt-proj
|
|||
|
||||
Reliable and comprehensive digital forensic support and triage requires access to non-public indicators, research and threat intelligence.
|
||||
|
||||
Such support is available to civil society through [Amnesty International's Security Lab](https://securitylab.amnesty.org/contact-us/) or [Access Now’s Digital Security Helpline](https://www.accessnow.org/help/).
|
||||
Such support is available to civil society through [Amnesty International's Security Lab](https://securitylab.amnesty.org/get-help/?c=mvt_docs) or [Access Now’s Digital Security Helpline](https://www.accessnow.org/help/).
|
||||
|
||||
More information about using indicators of compromise with MVT is available in the [documentation](iocs.md).
|
||||
|
||||
|
|
|
@ -160,6 +160,27 @@ class Command:
|
|||
def finish(self) -> None:
|
||||
raise NotImplementedError
|
||||
|
||||
def _show_disable_adb_warning(self) -> None:
|
||||
"""Warn if ADB is enabled"""
|
||||
if type(self).__name__ in ["CmdAndroidCheckADB", "CmdAndroidCheckAndroidQF"]:
|
||||
self.log.info(
|
||||
"Please disable Developer Options and ADB (Android Debug Bridge) on the device once finished with the acquisition. "
|
||||
"ADB is a powerful tool which can allow unauthorized access to the device."
|
||||
)
|
||||
|
||||
def _show_support_message(self) -> None:
|
||||
support_message = "Please seek reputable expert help if you have serious concerns about a possible spyware attack. Such support is available to human rights defenders and civil society through Amnesty International's Security Lab at https://securitylab.amnesty.org/get-help/?c=mvt"
|
||||
if self.detected_count == 0:
|
||||
self.log.info(
|
||||
f"[bold]NOTE:[/bold] Using MVT with public indicators of compromise (IOCs) [bold]WILL NOT[/bold] automatically detect advanced attacks.\n\n{support_message}",
|
||||
extra={"markup": True},
|
||||
)
|
||||
else:
|
||||
self.log.warning(
|
||||
f"[bold]NOTE: Detected indicators of compromise[/bold]. Only expert review can confirm if the detected indicators are signs of an attack.\n\n{support_message}",
|
||||
extra={"markup": True},
|
||||
)
|
||||
|
||||
def run(self) -> None:
|
||||
try:
|
||||
self.init()
|
||||
|
@ -208,3 +229,6 @@ class Command:
|
|||
|
||||
self._store_timeline()
|
||||
self._store_info()
|
||||
|
||||
self._show_disable_adb_warning()
|
||||
self._show_support_message()
|
||||
|
|
|
@ -9,47 +9,65 @@ import requests
|
|||
from tld import get_tld
|
||||
|
||||
SHORTENER_DOMAINS = [
|
||||
"0rz.tw",
|
||||
"1drv.ms",
|
||||
"1link.in",
|
||||
"1url.com",
|
||||
"2big.at",
|
||||
"2.gp",
|
||||
"2pl.us",
|
||||
"2tu.us",
|
||||
"2ya.com",
|
||||
"3.ly",
|
||||
"4sq.com",
|
||||
"4url.cc",
|
||||
"6url.com",
|
||||
"a.gg",
|
||||
"a.nf",
|
||||
"7.ly",
|
||||
"a2a.me",
|
||||
"abbrr.com",
|
||||
"adf.ly",
|
||||
"adjix.com",
|
||||
"a.gg",
|
||||
"alturl.com",
|
||||
"a.nf",
|
||||
"anon.to",
|
||||
"apple.news",
|
||||
"atu.ca",
|
||||
"b23.ru",
|
||||
"bacn.me",
|
||||
"bc.vc",
|
||||
"bfy.tw",
|
||||
"binged.it",
|
||||
"bit.do",
|
||||
"bit.ly",
|
||||
"bizj.us",
|
||||
"bkite.com",
|
||||
"bloat.me",
|
||||
"budurl.com",
|
||||
"buff.ly",
|
||||
"buk.me",
|
||||
"burnurl.com",
|
||||
"c-o.in",
|
||||
"chilp.it",
|
||||
"chn.ge",
|
||||
"clck.ru",
|
||||
"cli.gs",
|
||||
"clickmeter.com",
|
||||
"cli.gs",
|
||||
"c-o.in",
|
||||
"cort.as",
|
||||
"cut.ly",
|
||||
"cutt.ly",
|
||||
"cuturl.com",
|
||||
"decenturl.com",
|
||||
"dai.ly",
|
||||
"dailym.ai",
|
||||
"db.tt",
|
||||
"decenturl.com",
|
||||
"dfl8.me",
|
||||
"digbig.com",
|
||||
"digg.com",
|
||||
"disq.us",
|
||||
"dlvr.it",
|
||||
"doiop.com",
|
||||
"do.my",
|
||||
"dwarfurl.com",
|
||||
"dy.fi",
|
||||
"easyuri.com",
|
||||
|
@ -58,27 +76,35 @@ SHORTENER_DOMAINS = [
|
|||
"esyurl.com",
|
||||
"ewerl.com",
|
||||
"fa.b",
|
||||
"ff.im",
|
||||
"fa.by",
|
||||
"fb.me",
|
||||
"fff.to",
|
||||
"ff.im",
|
||||
"fhurl.com",
|
||||
"fire.to",
|
||||
"firsturl.de",
|
||||
"firsturl.net",
|
||||
"flic.kr",
|
||||
"flq.us",
|
||||
"fly2.ws",
|
||||
"fon.gs",
|
||||
"forms.gle",
|
||||
"fwd4.me",
|
||||
"gdurl.com",
|
||||
"gg.gg",
|
||||
"gl.am",
|
||||
"go.9nl.com",
|
||||
"go2.me",
|
||||
"go2cut.com",
|
||||
"go2.me",
|
||||
"go.9nl.com",
|
||||
"goo.gl",
|
||||
"goshrink.com",
|
||||
"got.by",
|
||||
"gowat.ch",
|
||||
"gri.ms",
|
||||
"gurl.es",
|
||||
"hellotxt.com",
|
||||
"hex.io",
|
||||
"hongkiat.shorturl.com",
|
||||
"hover.com",
|
||||
"href.in",
|
||||
"ht.ly",
|
||||
|
@ -87,13 +113,15 @@ SHORTENER_DOMAINS = [
|
|||
"hurl.it",
|
||||
"hurl.me",
|
||||
"hurl.ws",
|
||||
"ibb.co",
|
||||
"icanhaz.com",
|
||||
"idek.net",
|
||||
"inreply.to",
|
||||
"is.gd",
|
||||
"iscool.net",
|
||||
"is.gd",
|
||||
"iterasi.net",
|
||||
"jijr.com",
|
||||
"j.mp",
|
||||
"jmp2.net",
|
||||
"just.as",
|
||||
"kissa.be",
|
||||
|
@ -101,21 +129,23 @@ SHORTENER_DOMAINS = [
|
|||
"klck.me",
|
||||
"korta.nu",
|
||||
"krunchd.com",
|
||||
"lat.ms",
|
||||
"liip.to",
|
||||
"liltext.com",
|
||||
"lin.cr",
|
||||
"linkbee.com",
|
||||
"linkbun.ch",
|
||||
"liurl.cn",
|
||||
"ln-s.net",
|
||||
"ln-s.ru",
|
||||
"lnkd.in",
|
||||
"lnk.gd",
|
||||
"lnk.in",
|
||||
"lnkd.in",
|
||||
"ln-s.net",
|
||||
"ln-s.ru",
|
||||
"loopt.us",
|
||||
"lru.jp",
|
||||
"lt.tl",
|
||||
"lurl.no",
|
||||
"lyhyt.eu",
|
||||
"metamark.net",
|
||||
"migre.me",
|
||||
"minilien.com",
|
||||
|
@ -123,52 +153,71 @@ SHORTENER_DOMAINS = [
|
|||
"minurl.fr",
|
||||
"moourl.com",
|
||||
"myurl.in",
|
||||
"nbcnews.to",
|
||||
"ne1.net",
|
||||
"njx.me",
|
||||
"nn.nf",
|
||||
"notlong.com",
|
||||
"n.pr",
|
||||
"nsfw.in",
|
||||
"o-x.fr",
|
||||
"nyti.ms",
|
||||
"om.ly",
|
||||
"onforb.es",
|
||||
"on.mktw.net",
|
||||
"ow.ly",
|
||||
"o-x.fr",
|
||||
"pca.st",
|
||||
"pd.am",
|
||||
"pic.gd",
|
||||
"ping.fm",
|
||||
"piurl.com",
|
||||
"pnt.me",
|
||||
"politi.co",
|
||||
"poprl.com",
|
||||
"post.ly",
|
||||
"posted.at",
|
||||
"post.ly",
|
||||
"profile.to",
|
||||
"q.gs",
|
||||
"qicute.com",
|
||||
"qlnk.net",
|
||||
"qr.ae",
|
||||
"qte.me",
|
||||
"quip-art.com",
|
||||
"rb6.me",
|
||||
"rb.gy",
|
||||
"read.bi",
|
||||
"redir.ec",
|
||||
"redirx.com",
|
||||
"ri.ms",
|
||||
"redr.me",
|
||||
"reut.rs",
|
||||
"rickroll.it",
|
||||
"r.im",
|
||||
"ri.ms",
|
||||
"riz.gd",
|
||||
"rsmonkey.com",
|
||||
"ru.ly",
|
||||
"rubyurl.com",
|
||||
"ru.ly",
|
||||
"s7y.us",
|
||||
"safe.mn",
|
||||
"sharein.com",
|
||||
"sharetabs.com",
|
||||
"shorl.com",
|
||||
"short.ie",
|
||||
"short.to",
|
||||
"shortlinks.co.uk",
|
||||
"shortna.me",
|
||||
"short.to",
|
||||
"shorturl.at",
|
||||
"shorturl.com",
|
||||
"shoturl.us",
|
||||
"shout.to",
|
||||
"shrinkify.com",
|
||||
"shrinkster.com",
|
||||
"shrt.st",
|
||||
"shrten.com",
|
||||
"shrt.st",
|
||||
"shrunkin.com",
|
||||
"shw.me",
|
||||
"simurl.com",
|
||||
"smsh.me",
|
||||
"sn.im",
|
||||
"snipr.com",
|
||||
"snipurl.com",
|
||||
|
@ -179,24 +228,30 @@ SHORTENER_DOMAINS = [
|
|||
"starturl.com",
|
||||
"sturly.com",
|
||||
"su.pr",
|
||||
"t.cn",
|
||||
"t.co",
|
||||
"tcrn.ch",
|
||||
"tgr.ph",
|
||||
"thrdl.es",
|
||||
"tighturl.com",
|
||||
"tiny.cc",
|
||||
"tiny.pl",
|
||||
"tiny123.com",
|
||||
"tinyarro.ws",
|
||||
"tiny.cc",
|
||||
"tinylink.in",
|
||||
"tiny.pl",
|
||||
"tiny.tw",
|
||||
"tinytw.it",
|
||||
"tinyuri.ca",
|
||||
"tinyurl.com",
|
||||
"tinyvid.io",
|
||||
"t.me",
|
||||
"tnij.org",
|
||||
"to.ly",
|
||||
"tnw.to",
|
||||
"togoto.us",
|
||||
"to.ly",
|
||||
"traceurl.com",
|
||||
"tr.im",
|
||||
"tr.my",
|
||||
"traceurl.com",
|
||||
"turo.us",
|
||||
"tweetburner.com",
|
||||
"twirl.at",
|
||||
|
@ -206,49 +261,62 @@ SHORTENER_DOMAINS = [
|
|||
"twiturl.de",
|
||||
"twurl.cc",
|
||||
"twurl.nl",
|
||||
"u.mavrev.com",
|
||||
"u.nu",
|
||||
"u6e.de",
|
||||
"ub0.cc",
|
||||
"ukl.me.uk",
|
||||
"u.mavrev.com",
|
||||
"u.nu",
|
||||
"updating.me",
|
||||
"ur1.ca",
|
||||
"url.co.uk",
|
||||
"url.ie",
|
||||
"url4.eu",
|
||||
"urlao.com",
|
||||
"urlbrief.com",
|
||||
"url.co.uk",
|
||||
"urlcover.com",
|
||||
"urlcut.com",
|
||||
"urlenco.de",
|
||||
"urlhawk.com",
|
||||
"url.ie",
|
||||
"urlkiss.com",
|
||||
"urlot.com",
|
||||
"urlpire.com",
|
||||
"urlx.ie",
|
||||
"urlx.org",
|
||||
"urlzen.com",
|
||||
"use.my",
|
||||
"u.to",
|
||||
"v.gd",
|
||||
"virl.com",
|
||||
"vl.am",
|
||||
"vurl.com",
|
||||
"vzturl.com",
|
||||
"w3t.org",
|
||||
"wapo.st",
|
||||
"wapurl.co.uk",
|
||||
"wipi.es",
|
||||
"wp.me",
|
||||
"x.co",
|
||||
"x.se",
|
||||
"xaddr.com",
|
||||
"x.co",
|
||||
"xeeurl.com",
|
||||
"xr.com",
|
||||
"xrl.in",
|
||||
"xrl.us",
|
||||
"x.se",
|
||||
"xurl.es",
|
||||
"xurl.jp",
|
||||
"xzb.cc",
|
||||
"ye.pe",
|
||||
"yep.it",
|
||||
"yfrog.com",
|
||||
"yhoo.it",
|
||||
"ymlp.com",
|
||||
"yuarel.com",
|
||||
"yweb.com",
|
||||
"zi.ma",
|
||||
"zi.pe",
|
||||
"zipmyurl.com",
|
||||
"zurl.to",
|
||||
"zurl.ws",
|
||||
"zz.gd",
|
||||
]
|
||||
|
||||
|
|
|
@ -53,20 +53,20 @@ def convert_chrometime_to_datetime(timestamp: int) -> datetime.datetime:
|
|||
def convert_datetime_to_iso(date_time: datetime.datetime) -> str:
|
||||
"""Converts datetime to ISO string.
|
||||
|
||||
:param datetime: datetime.
|
||||
:param datetime: datetime, naive or timezone aware
|
||||
:type datetime: datetime.datetime
|
||||
:returns: ISO datetime string in YYYY-mm-dd HH:MM:SS.ms format.
|
||||
:rtype: str
|
||||
|
||||
"""
|
||||
try:
|
||||
return date_time.strftime("%Y-%m-%d %H:%M:%S.%f")
|
||||
except Exception:
|
||||
return ""
|
||||
if date_time.tzinfo:
|
||||
# Timezone aware object - convert to UTC
|
||||
date_time = date_time.astimezone(tz=datetime.timezone.utc)
|
||||
return date_time.strftime("%Y-%m-%d %H:%M:%S.%f")
|
||||
|
||||
|
||||
def convert_unix_to_utc_datetime(
|
||||
timestamp: Union[int, float, str]
|
||||
timestamp: Union[int, float, str],
|
||||
) -> datetime.datetime:
|
||||
"""Converts a unix epoch timestamp to UTC datetime.
|
||||
|
||||
|
|
|
@ -3,4 +3,4 @@
|
|||
# Use of this software is governed by the MVT License 1.1 that can be found at
|
||||
# https://license.mvt.re/1.1/
|
||||
|
||||
MVT_VERSION = "2.5.0"
|
||||
MVT_VERSION = "2.5.3"
|
||||
|
|
|
@ -66,8 +66,11 @@ class SMS(IOSExtraction):
|
|||
|
||||
def check_indicators(self) -> None:
|
||||
for message in self.results:
|
||||
alert = "ALERT: State-sponsored attackers may be targeting your iPhone"
|
||||
if message.get("text", "").startswith(alert):
|
||||
alert_old = "ALERT: State-sponsored attackers may be targeting your iPhone"
|
||||
alert_new = "ALERT: Apple detected a targeted mercenary spyware attack against your iPhone"
|
||||
if message.get("text", "").startswith(alert_old) or message.get(
|
||||
"text", ""
|
||||
).startswith(alert_new):
|
||||
self.log.warning(
|
||||
"Apple warning about state-sponsored attack received on the %s",
|
||||
message["isodate"],
|
||||
|
|
|
@ -31,7 +31,7 @@ install_requires =
|
|||
iOSbackup >=0.9.923
|
||||
adb-shell >=0.4.3
|
||||
libusb1 >=3.0.0
|
||||
cryptography >=38.0.1
|
||||
cryptography >=42.0.5
|
||||
pyyaml >=6.0
|
||||
pyahocorasick >= 2.0.0
|
||||
|
||||
|
|
|
@ -42,6 +42,14 @@ class TestDateConversions:
|
|||
converted = convert_unix_to_utc_datetime(TEST_DATE_EPOCH)
|
||||
assert convert_datetime_to_iso(converted) == TEST_DATE_ISO
|
||||
|
||||
def test_convert_timezone_aware_to_iso(self):
|
||||
assert (
|
||||
convert_datetime_to_iso(
|
||||
datetime.strptime("2024-09-30 11:21:20+0200", "%Y-%m-%d %H:%M:%S%z")
|
||||
)
|
||||
== "2024-09-30 09:21:20.000000"
|
||||
)
|
||||
|
||||
|
||||
class TestHashes:
|
||||
def test_hash_from_file(self):
|
||||
|
|
Loading…
Reference in New Issue