mirror of
https://github.com/mvt-project/mvt.git
synced 2026-02-12 16:42:45 +00:00
Add support for check APK certificate hash IOCs (#557)
* Fix bug loading indicators which I introduced in 81b647b
* Add support for matching on APK certificate hash IOCs
This commit is contained in:
committed by
GitHub
parent
665806db98
commit
3afe218c7c
@@ -77,7 +77,6 @@ class Packages(AndroidQFModule):
|
||||
if ioc:
|
||||
result["matched_indicator"] = ioc
|
||||
self.detected.append(result)
|
||||
continue
|
||||
|
||||
for package_file in result.get("files", []):
|
||||
ioc = self.indicators.check_file_hash(package_file["sha256"])
|
||||
@@ -85,6 +84,18 @@ class Packages(AndroidQFModule):
|
||||
result["matched_indicator"] = ioc
|
||||
self.detected.append(result)
|
||||
|
||||
if "certificate" not in package_file:
|
||||
continue
|
||||
|
||||
# The keys generated by AndroidQF have a leading uppercase character
|
||||
for hash_type in ["Md5", "Sha1", "Sha256"]:
|
||||
certificate_hash = package_file["certificate"][hash_type]
|
||||
ioc = self.indicators.check_app_certificate_hash(certificate_hash)
|
||||
if ioc:
|
||||
result["matched_indicator"] = ioc
|
||||
self.detected.append(result)
|
||||
break
|
||||
|
||||
def run(self) -> None:
|
||||
packages = self._get_files_by_pattern("*/packages.json")
|
||||
if not packages:
|
||||
|
||||
@@ -82,6 +82,7 @@ class Indicators:
|
||||
"files_md5": [],
|
||||
"files_sha1": [],
|
||||
"files_sha256": [],
|
||||
"app_cert_hashes": [],
|
||||
"app_ids": [],
|
||||
"ios_profile_ids": [],
|
||||
"android_property_names": [],
|
||||
@@ -107,7 +108,7 @@ class Indicators:
|
||||
ioc_coll=collection,
|
||||
ioc_coll_list=collection["domains"],
|
||||
)
|
||||
if key == "ipv4-addr:value":
|
||||
elif key == "ipv4-addr:value":
|
||||
# We treat IP addresses as simple domains here to ease checks.
|
||||
self._add_indicator(
|
||||
ioc=value.strip(),
|
||||
@@ -145,6 +146,24 @@ class Indicators:
|
||||
self._add_indicator(
|
||||
ioc=value, ioc_coll=collection, ioc_coll_list=collection["files_sha256"]
|
||||
)
|
||||
elif key == "app:cert.md5":
|
||||
self._add_indicator(
|
||||
ioc=value,
|
||||
ioc_coll=collection,
|
||||
ioc_coll_list=collection["app_cert_hashes"],
|
||||
)
|
||||
elif key == "app:cert.sha1":
|
||||
self._add_indicator(
|
||||
ioc=value,
|
||||
ioc_coll=collection,
|
||||
ioc_coll_list=collection["app_cert_hashes"],
|
||||
)
|
||||
elif key == "app:cert.sha256":
|
||||
self._add_indicator(
|
||||
ioc=value,
|
||||
ioc_coll=collection,
|
||||
ioc_coll_list=collection["app_cert_hashes"],
|
||||
)
|
||||
elif key == "app:id":
|
||||
self._add_indicator(
|
||||
ioc=value, ioc_coll=collection, ioc_coll_list=collection["app_ids"]
|
||||
@@ -155,7 +174,6 @@ class Indicators:
|
||||
ioc_coll=collection,
|
||||
ioc_coll_list=collection["ios_profile_ids"],
|
||||
)
|
||||
|
||||
elif key == "android-property:name":
|
||||
self._add_indicator(
|
||||
ioc=value,
|
||||
@@ -703,6 +721,29 @@ class Indicators:
|
||||
|
||||
return None
|
||||
|
||||
def check_app_certificate_hash(self, cert_hash: str) -> Union[dict, None]:
|
||||
"""Check the provided cert hash against the list of indicators.
|
||||
|
||||
:param cert_hash: hash to check
|
||||
:type cert_hash: str
|
||||
:returns: Indicator details if matched, otherwise None
|
||||
|
||||
"""
|
||||
if not cert_hash:
|
||||
return None
|
||||
|
||||
for ioc in self.get_iocs("app_cert_hashes"):
|
||||
if cert_hash.lower() == ioc["value"].lower():
|
||||
self.log.warning(
|
||||
'Found a known suspicious app certfificate with hash "%s" '
|
||||
'matching indicators from "%s"',
|
||||
cert_hash,
|
||||
ioc["name"],
|
||||
)
|
||||
return ioc
|
||||
|
||||
return None
|
||||
|
||||
def check_app_id(self, app_id: str) -> Union[dict, None]:
|
||||
"""Check the provided app identifier (typically an Android package name)
|
||||
against the list of indicators.
|
||||
|
||||
@@ -86,3 +86,19 @@ class TestAndroidqfPackages:
|
||||
module.detected[0]["matched_indicator"]["value"]
|
||||
== "31037a27af59d4914906c01ad14a318eee2f3e31d48da8954dca62a99174e3fa"
|
||||
)
|
||||
|
||||
def test_packages_certificate_hash_ioc(self, module, indicators_factory):
|
||||
module.indicators = indicators_factory(
|
||||
app_cert_hashes=[
|
||||
"c7e56178748be1441370416d4c10e34817ea0c961eb636c8e9d98e0fd79bf730"
|
||||
]
|
||||
)
|
||||
|
||||
run_module(module)
|
||||
|
||||
assert len(module.detected) == 1
|
||||
assert module.detected[0]["name"] == "com.malware.muahaha"
|
||||
assert (
|
||||
module.detected[0]["matched_indicator"]["value"]
|
||||
== "c7e56178748be1441370416d4c10e34817ea0c961eb636c8e9d98e0fd79bf730"
|
||||
)
|
||||
|
||||
@@ -212,7 +212,7 @@
|
||||
"certificate": {
|
||||
"Md5": "54d5b5aca1e7e76bb1a26c61a9381b93",
|
||||
"Sha1": "4ba9d1f82adb7be841bcf53b03ddae857747199a",
|
||||
"Sha256": "31037a27af59d4914906c01ad14a318eee2f3e31d48da8954dca62a99174e3fa",
|
||||
"Sha256": "c7e56178748be1441370416d4c10e34817ea0c961eb636c8e9d98e0fd79bf730",
|
||||
"ValidFrom": "2021-01-15T22:03:53Z",
|
||||
"ValidTo": "2051-01-15T22:03:53Z",
|
||||
"Issuer": "C=US, ST=California, L=Mountain View, O=Google Inc., OU=Android, CN=Android",
|
||||
|
||||
@@ -37,6 +37,7 @@ def indicators_factory(indicator_file):
|
||||
file_names=[],
|
||||
processes=[],
|
||||
app_ids=[],
|
||||
app_cert_hashes=[],
|
||||
android_property_names=[],
|
||||
files_sha256=[],
|
||||
):
|
||||
@@ -50,6 +51,7 @@ def indicators_factory(indicator_file):
|
||||
ind.ioc_collections[0]["app_ids"].extend(app_ids)
|
||||
ind.ioc_collections[0]["android_property_names"].extend(android_property_names)
|
||||
ind.ioc_collections[0]["files_sha256"].extend(files_sha256)
|
||||
ind.ioc_collections[0]["app_cert_hashes"].extend(app_cert_hashes)
|
||||
|
||||
return ind
|
||||
|
||||
|
||||
Reference in New Issue
Block a user