Compare commits

...

6 Commits

Author SHA1 Message Date
tek
17b58ac90b Fixes bug in IOC import 2026-03-25 18:20:34 -04:00
dependabot[bot]
5cba61b180 Bump mkdocstrings from 0.30.1 to 1.0.0 (#730)
Bumps [mkdocstrings](https://github.com/mkdocstrings/mkdocstrings) from 0.30.1 to 1.0.0.
- [Release notes](https://github.com/mkdocstrings/mkdocstrings/releases)
- [Changelog](https://github.com/mkdocstrings/mkdocstrings/blob/main/CHANGELOG.md)
- [Commits](https://github.com/mkdocstrings/mkdocstrings/compare/0.30.1...1.0.0)

---
updated-dependencies:
- dependency-name: mkdocstrings
  dependency-version: 1.0.0
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: besendorf <janik@besendorf.org>
2026-03-25 15:24:07 +01:00
dependabot[bot]
29475acb47 Bump click from 8.3.0 to 8.3.1 (#731)
Bumps [click](https://github.com/pallets/click) from 8.3.0 to 8.3.1.
- [Release notes](https://github.com/pallets/click/releases)
- [Changelog](https://github.com/pallets/click/blob/main/CHANGES.rst)
- [Commits](https://github.com/pallets/click/compare/8.3.0...8.3.1)

---
updated-dependencies:
- dependency-name: click
  dependency-version: 8.3.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: besendorf <janik@besendorf.org>
2026-03-25 14:37:59 +01:00
dependabot[bot]
1d5c83582c Bump pydantic from 2.12.3 to 2.12.5 (#732)
Bumps [pydantic](https://github.com/pydantic/pydantic) from 2.12.3 to 2.12.5.
- [Release notes](https://github.com/pydantic/pydantic/releases)
- [Changelog](https://github.com/pydantic/pydantic/blob/main/HISTORY.md)
- [Commits](https://github.com/pydantic/pydantic/compare/v2.12.3...v2.12.5)

---
updated-dependencies:
- dependency-name: pydantic
  dependency-version: 2.12.5
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: besendorf <janik@besendorf.org>
2026-03-25 14:26:09 +01:00
dependabot[bot]
2dd1428787 Bump cryptography from 46.0.3 to 46.0.5 (#747)
Bumps [cryptography](https://github.com/pyca/cryptography) from 46.0.3 to 46.0.5.
- [Changelog](https://github.com/pyca/cryptography/blob/main/CHANGELOG.rst)
- [Commits](https://github.com/pyca/cryptography/compare/46.0.3...46.0.5)

---
updated-dependencies:
- dependency-name: cryptography
  dependency-version: 46.0.5
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-03-25 08:49:46 +01:00
besendorf
f2d9f420f2 Detect uninstall and downgrade in battery daily (#736) 2026-03-16 12:32:54 +01:00
4 changed files with 61 additions and 22 deletions

View File

@@ -2,4 +2,4 @@ mkdocs==1.6.1
mkdocs-autorefs==1.4.3 mkdocs-autorefs==1.4.3
mkdocs-material==9.6.20 mkdocs-material==9.6.20
mkdocs-material-extensions==1.3.1 mkdocs-material-extensions==1.3.1
mkdocstrings==0.30.1 mkdocstrings==1.0.0

View File

@@ -17,7 +17,7 @@ classifiers = [
"Programming Language :: Python", "Programming Language :: Python",
] ]
dependencies = [ dependencies = [
"click==8.3.0", "click==8.3.1",
"rich==14.1.0", "rich==14.1.0",
"tld==0.13.1", "tld==0.13.1",
"requests==2.32.5", "requests==2.32.5",
@@ -27,11 +27,11 @@ dependencies = [
"iOSbackup==0.9.925", "iOSbackup==0.9.925",
"adb-shell[usb]==0.4.4", "adb-shell[usb]==0.4.4",
"libusb1==3.3.1", "libusb1==3.3.1",
"cryptography==46.0.3", "cryptography==46.0.5",
"PyYAML>=6.0.2", "PyYAML>=6.0.2",
"pyahocorasick==2.2.0", "pyahocorasick==2.2.0",
"betterproto==1.2.5", "betterproto==1.2.5",
"pydantic==2.12.3", "pydantic==2.12.5",
"pydantic-settings==2.10.1", "pydantic-settings==2.10.1",
"NSKeyedUnArchiver==1.5.2", "NSKeyedUnArchiver==1.5.2",
"python-dateutil==2.9.0.post0", "python-dateutil==2.9.0.post0",
@@ -81,8 +81,8 @@ addopts = "-ra -q --cov=mvt --cov-report html --junitxml=pytest.xml --cov-report
testpaths = ["tests"] testpaths = ["tests"]
[tool.ruff] [tool.ruff]
select = ["C90", "E", "F", "W"] # flake8 default set lint.select = ["C90", "E", "F", "W"] # flake8 default set
ignore = [ lint.ignore = [
"E501", # don't enforce line length violations "E501", # don't enforce line length violations
"C901", # complex-structure "C901", # complex-structure
@@ -95,10 +95,10 @@ ignore = [
# "E203", # whitespace-before-punctuation # "E203", # whitespace-before-punctuation
] ]
[tool.ruff.per-file-ignores] [tool.ruff.lint.per-file-ignores]
"__init__.py" = ["F401"] # unused-import "__init__.py" = ["F401"] # unused-import
[tool.ruff.mccabe] [tool.ruff.lint.mccabe]
max-complexity = 10 max-complexity = 10
[tool.setuptools] [tool.setuptools]

View File

@@ -14,12 +14,23 @@ class DumpsysBatteryDailyArtifact(AndroidArtifact):
""" """
def serialize(self, record: dict) -> Union[dict, list]: def serialize(self, record: dict) -> Union[dict, list]:
action = record.get("action", "update")
package_name = record["package_name"]
vers = record["vers"]
if vers == "0":
data = f"Recorded uninstall of package {package_name} (vers 0)"
elif action == "downgrade":
prev_vers = record.get("previous_vers", "unknown")
data = f"Recorded downgrade of package {package_name} from vers {prev_vers} to vers {vers}"
else:
data = f"Recorded update of package {package_name} with vers {vers}"
return { return {
"timestamp": record["from"], "timestamp": record["from"],
"module": self.__class__.__name__, "module": self.__class__.__name__,
"event": "battery_daily", "event": "battery_daily",
"data": f"Recorded update of package {record['package_name']} " "data": data,
f"with vers {record['vers']}",
} }
def check_indicators(self) -> None: def check_indicators(self) -> None:
@@ -36,6 +47,7 @@ class DumpsysBatteryDailyArtifact(AndroidArtifact):
def parse(self, output: str) -> None: def parse(self, output: str) -> None:
daily = None daily = None
daily_updates = [] daily_updates = []
package_versions = {} # Track package versions to detect downgrades
for line in output.splitlines(): for line in output.splitlines():
if line.startswith(" Daily from "): if line.startswith(" Daily from "):
if len(daily_updates) > 0: if len(daily_updates) > 0:
@@ -64,15 +76,44 @@ class DumpsysBatteryDailyArtifact(AndroidArtifact):
break break
if not already_seen: if not already_seen:
daily_updates.append( update_record = {
{ "action": "update",
"action": "update", "from": daily["from"],
"from": daily["from"], "to": daily["to"],
"to": daily["to"], "package_name": package_name,
"package_name": package_name, "vers": vers_nr,
"vers": vers_nr, }
}
) # Check for uninstall (version 0)
if vers_nr == "0":
self.log.warning(
"Detected uninstall of package %s (vers 0) on %s",
package_name,
daily["from"],
)
# Check for downgrade
elif package_name in package_versions:
try:
current_vers = int(vers_nr)
previous_vers = int(package_versions[package_name])
if current_vers < previous_vers:
update_record["action"] = "downgrade"
update_record["previous_vers"] = str(previous_vers)
self.log.warning(
"Detected downgrade of package %s from vers %d to vers %d on %s",
package_name,
previous_vers,
current_vers,
daily["from"],
)
except ValueError:
# If version numbers aren't integers, skip comparison
pass
# Update tracking dictionary
package_versions[package_name] = vers_nr
daily_updates.append(update_record)
if len(daily_updates) > 0: if len(daily_updates) > 0:
self.results.extend(daily_updates) self.results.extend(daily_updates)

View File

@@ -52,9 +52,7 @@ class Indicators:
if os.path.isfile(path) and path.lower().endswith(".stix2"): if os.path.isfile(path) and path.lower().endswith(".stix2"):
self.parse_stix2(path) self.parse_stix2(path)
elif os.path.isdir(path): elif os.path.isdir(path):
for file in glob.glob( for file in glob.glob(os.path.join(path, "**", "*.stix2"), recursive=True):
os.path.join(path, "**", "*.stix2", recursive=True)
):
self.parse_stix2(file) self.parse_stix2(file)
else: else:
self.log.error( self.log.error(