1
mirror of https://github.com/mvt-project/mvt synced 2025-10-21 22:42:15 +02:00

Compare commits

...

5 Commits

Author SHA1 Message Date
Nex
7b107edf1f Bumped version 2022-02-01 17:54:01 +01:00
Nex
b97ce7651a Fixed missing checks for indicators instance (ref: #245) 2022-02-01 17:48:19 +01:00
Nex
52a204cab6 Obtaining permissions for installed packages 2022-02-01 15:33:19 +01:00
Nex
1b335fda1d Renamed function argument to more descriptive 2022-02-01 15:07:43 +01:00
Nex
2ad175eae2 Renamed package to package_name for consistency 2022-02-01 14:27:00 +01:00
9 changed files with 125 additions and 41 deletions

View File

@@ -20,8 +20,11 @@ class DumpsysAccessibility(AndroidExtraction):
log=log, results=results)
def check_indicators(self):
if not self.indicators:
return
for result in self.results:
ioc = self.indicators.check_app_id(result["package"])
ioc = self.indicators.check_app_id(result["package_name"])
if ioc:
result["matched_indicator"] = ioc
self.detected.append(result)
@@ -47,7 +50,7 @@ class DumpsysAccessibility(AndroidExtraction):
log.info("Found installed accessibility service \"%s\"", service)
results.append({
"package": service.split("/")[0],
"package_name": service.split("/")[0],
"service": service,
})

View File

@@ -22,9 +22,12 @@ class DumpsysActivities(AndroidExtraction):
self.results = results if results else {}
def check_indicators(self):
if not self.indicators:
return
for intent, activities in self.results.items():
for activity in activities:
ioc = self.indicators.check_app_id(activity["package"])
ioc = self.indicators.check_app_id(activity["package_name"])
if ioc:
activity["matched_indicator"] = ioc
self.detected.append({intent: activity})
@@ -77,10 +80,10 @@ class DumpsysActivities(AndroidExtraction):
# If we got this far, we are processing receivers for the
# activities we are interested in.
activity = line.strip().split(" ")[1]
package = activity.split("/")[0]
package_name = activity.split("/")[0]
results[intent].append({
"package": package,
"package_name": package_name,
"activity": activity,
})

View File

@@ -24,12 +24,15 @@ class DumpsysBatteryDaily(AndroidExtraction):
"timestamp": record["from"],
"module": self.__class__.__name__,
"event": "battery_daily",
"data": f"Recorded update of package {record['package']} with vers {record['vers']}"
"data": f"Recorded update of package {record['package_name']} with vers {record['vers']}"
}
def check_indicators(self):
if not self.indicators:
return
for result in self.results:
ioc = self.indicators.check_app_id(result["package"])
ioc = self.indicators.check_app_id(result["package_name"])
if ioc:
result["matched_indicator"] = ioc
self.detected.append(result)
@@ -59,12 +62,12 @@ class DumpsysBatteryDaily(AndroidExtraction):
continue
line = line.strip().replace("Update ", "")
package, vers = line.split(" ", 1)
package_name, vers = line.split(" ", 1)
vers_nr = vers.split("=", 1)[1]
already_seen = False
for update in daily_updates:
if package == update["package"] and vers_nr == update["vers"]:
if package_name == update["package_name"] and vers_nr == update["vers"]:
already_seen = True
break
@@ -73,7 +76,7 @@ class DumpsysBatteryDaily(AndroidExtraction):
"action": "update",
"from": daily["from"],
"to": daily["to"],
"package": package,
"package_name": package_name,
"vers": vers_nr,
})

View File

@@ -20,8 +20,11 @@ class DumpsysBatteryHistory(AndroidExtraction):
log=log, results=results)
def check_indicators(self):
if not self.indicators:
return
for result in self.results:
ioc = self.indicators.check_app_id(result["package"])
ioc = self.indicators.check_app_id(result["package_name"])
if ioc:
result["matched_indicator"] = ioc
self.detected.append(result)
@@ -56,14 +59,14 @@ class DumpsysBatteryHistory(AndroidExtraction):
if event in ["start_job", "end_job"]:
uid = line[line.find("=")+1:line.find(":")]
service = line[line.find(":")+1:].strip('"')
package = service.split("/")[0]
package_name = service.split("/")[0]
elif event == "wake":
uid = line[line.find("=")+1:line.find(":")]
service = line[line.find("*walarm*:")+9:].split(" ")[0].strip('"').strip()
if service == "" or "/" not in service:
continue
package = service.split("/")[0]
package_name = service.split("/")[0]
else:
continue
@@ -71,7 +74,7 @@ class DumpsysBatteryHistory(AndroidExtraction):
"time_elapsed": time_elapsed,
"event": event,
"uid": uid,
"package": package,
"package_name": package_name,
"service": service,
})

View File

@@ -23,6 +23,9 @@ class DumpsysDBInfo(AndroidExtraction):
log=log, results=results)
def check_indicators(self):
if not self.indicators:
return
for result in self.results:
path = result.get("path", "")
for part in path.split("/"):

View File

@@ -28,6 +28,9 @@ class DumpsysReceivers(AndroidExtraction):
self.results = results if results else {}
def check_indicators(self):
if not self.indicators:
return
for intent, receivers in self.results.items():
for receiver in receivers:
if intent == INTENT_NEW_OUTGOING_SMS:
@@ -46,7 +49,7 @@ class DumpsysReceivers(AndroidExtraction):
self.log.info("Found a receiver monitoring outgoing calls: \"%s\"",
receiver["receiver"])
ioc = self.indicators.check_app_id(receiver["package"])
ioc = self.indicators.check_app_id(receiver["package_name"])
if ioc:
receiver["matched_indicator"] = ioc
self.detected.append({intent: receiver})
@@ -99,10 +102,10 @@ class DumpsysReceivers(AndroidExtraction):
# If we got this far, we are processing receivers for the
# activities we are interested in.
receiver = line.strip().split(" ")[1]
package = receiver.split("/")[0]
package_name = receiver.split("/")[0]
results[intent].append({
"package": package,
"package_name": package_name,
"receiver": receiver,
})

View File

@@ -24,9 +24,9 @@ class Files(AndroidExtraction):
log=log, results=results)
self.full_find = False
def find_files(self, file_path):
def find_files(self, folder):
if self.full_find:
output = self._adb_command(f"find '{file_path}' -printf '%T@ %m %s %u %g %p\n' 2> /dev/null")
output = self._adb_command(f"find '{folder}' -printf '%T@ %m %s %u %g %p\n' 2> /dev/null")
for file_line in output.splitlines():
[unix_timestamp, mode, size, owner, group, full_path] = file_line.rstrip().split(" ", 5)
@@ -42,7 +42,7 @@ class Files(AndroidExtraction):
"group": group,
})
else:
output = self._adb_command(f"find '{file_path}' 2> /dev/null")
output = self._adb_command(f"find '{folder}' 2> /dev/null")
for file_line in output.splitlines():
self.results.append({"path": file_line.rstrip()})

View File

@@ -15,6 +15,29 @@ from .base import AndroidExtraction
log = logging.getLogger(__name__)
DANGEROUS_PERMISSIONS_THRESHOLD = 10
DANGEROUS_PERMISSIONS = [
"android.permission.ACCESS_COARSE_LOCATION",
"android.permission.ACCESS_FINE_LOCATION",
"android.permission.AUTHENTICATE_ACCOUNTS",
"android.permission.CAMERA",
"android.permission.DISABLE_KEYGUARD",
"android.permission.PROCESS_OUTGOING_CALLS",
"android.permission.READ_CALENDAR",
"android.permission.READ_CALL_LOG",
"android.permission.READ_CONTACTS",
"android.permission.READ_PHONE_STATE",
"android.permission.READ_SMS",
"android.permission.RECEIVE_MMS",
"android.permission.RECEIVE_SMS",
"android.permission.RECEIVE_WAP_PUSH",
"android.permission.RECORD_AUDIO",
"android.permission.SEND_SMS",
"android.permission.SYSTEM_ALERT_WINDOW",
"android.permission.USE_CREDENTIALS",
"android.permission.USE_SIP",
"com.android.browser.permission.READ_HISTORY_BOOKMARKS",
]
class Packages(AndroidExtraction):
"""This module extracts the list of installed packages."""
@@ -57,6 +80,9 @@ class Packages(AndroidExtraction):
self.detected.append(result)
continue
if not self.indicators:
continue
ioc = self.indicators.check_app_id(result.get("package_name"))
if ioc:
result["matched_indicator"] = ioc
@@ -69,6 +95,45 @@ class Packages(AndroidExtraction):
result["matched_indicator"] = ioc
self.detected.append(result)
def _get_package_details(self, package_name):
details = {
"uid": "",
"version_name": "",
"version_code": "",
"timestamp": "",
"first_install_time": "",
"last_update_time": "",
"requested_permissions": [],
}
in_permissions = False
for line in self._adb_command(f"dumpsys package {package_name}").split("\n"):
if in_permissions:
if line.startswith(" " * 4) and not line.startswith(" " * 6):
in_permissions = False
continue
permission = line.strip().split(":")[0]
details["requested_permissions"].append(permission)
if line.strip().startswith("userId="):
details["uid"] = line.split("=")[1].strip()
elif line.strip().startswith("versionName="):
details["version_name"] = line.split("=")[1].strip()
elif line.strip().startswith("versionCode="):
details["version_code"] = line.split("=", 1)[1].strip()
elif line.strip().startswith("timeStamp="):
details["timestamp"] = line.split("=")[1].strip()
elif line.strip().startswith("firstInstallTime="):
details["first_install_time"] = line.split("=")[1].strip()
elif line.strip().startswith("lastUpdateTime="):
details["last_update_time"] = line.split("=")[1].strip()
elif line.strip() == "requested permissions:":
in_permissions = True
continue
return details
def _get_files_for_package(self, package_name):
output = self._adb_command(f"pm path {package_name}")
output = output.strip().replace("package:", "")
@@ -97,9 +162,7 @@ class Packages(AndroidExtraction):
def run(self):
self._adb_connect()
packages = self._adb_command("pm list packages -U -u -i -f")
if packages.strip() == "Error: Unknown option: -U":
packages = self._adb_command("pm list packages -u -i -f")
packages = self._adb_command("pm list packages -u -i -f")
for line in packages.split("\n"):
line = line.strip()
@@ -117,31 +180,21 @@ class Packages(AndroidExtraction):
if installer == "null":
installer = None
try:
uid = fields[2].split(":")[1].strip()
except IndexError:
uid = None
dumpsys = self._adb_command(f"dumpsys package {package_name} | grep -A2 timeStamp").split("\n")
timestamp = dumpsys[0].split("=")[1].strip()
first_install = dumpsys[1].split("=")[1].strip()
last_update = dumpsys[2].split("=")[1].strip()
package_files = self._get_files_for_package(package_name)
self.results.append({
new_package = {
"package_name": package_name,
"file_name": file_name,
"installer": installer,
"timestamp": timestamp,
"first_install_time": first_install,
"last_update_time": last_update,
"uid": uid,
"disabled": False,
"system": False,
"third_party": False,
"files": package_files,
})
}
package_details = self._get_package_details(package_name)
new_package.update(package_details)
self.results.append(new_package)
cmds = [
{"field": "disabled", "arg": "-d"},
@@ -160,6 +213,19 @@ class Packages(AndroidExtraction):
if result["package_name"] == package_name:
self.results[i][cmd["field"]] = True
for result in self.results:
if not result["third_party"]:
continue
dangerous_permissions_count = 0
for perm in result["requested_permissions"]:
if perm in DANGEROUS_PERMISSIONS:
dangerous_permissions_count += 1
if dangerous_permissions_count >= DANGEROUS_PERMISSIONS_THRESHOLD:
self.log.info("Third-party package \"%s\" requested %d potentially dangerous permissions",
result["package_name"], dangerous_permissions_count)
packages_to_lookup = []
for result in self.results:
if result["system"]:

View File

@@ -6,7 +6,7 @@
import requests
from packaging import version
MVT_VERSION = "1.4.10"
MVT_VERSION = "1.4.11"
def check_for_updates():