Skip to content
Merged
Show file tree
Hide file tree
Changes from 10 commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
25405b1
added permhash analyzer and updated project-requirements.txt
moonpatel Apr 5, 2024
5aeb924
name change
moonpatel Apr 5, 2024
e4ae82d
migrations
moonpatel Apr 5, 2024
58db127
changes
moonpatel Apr 5, 2024
72f93af
Merge branch 'develop' into permhash_analyzer
moonpatel Apr 8, 2024
1f47136
update mimetypes and migration file
moonpatel Apr 11, 2024
48f4e5b
update permhash
moonpatel Apr 11, 2024
3575fc1
fix migration issues
moonpatel Apr 11, 2024
eb95b87
raise AnalyzerRunException in perm_hash.py
moonpatel Apr 11, 2024
aef6de1
use mimetype instead of file extension
moonpatel Apr 11, 2024
2941901
Merge branch 'develop' into permhash_analyzer
moonpatel Apr 11, 2024
140617d
added monkeypatch patches and changed permhash version from 0.1.4.2 t…
moonpatel Apr 13, 2024
b00ee51
add permhash to free analyzers
moonpatel Apr 13, 2024
f0bf7c6
updated test_classes
moonpatel Apr 13, 2024
b9bf668
updated perm_hash.py
moonpatel Apr 13, 2024
1f715c3
added permhash to both free analyzers and static analyzers
moonpatel Apr 13, 2024
47348cd
updated Usage.md
moonpatel Apr 13, 2024
f32b959
Merge branch 'develop' into permhash_analyzer
moonpatel Apr 15, 2024
59cebe5
updated migrations
moonpatel Apr 15, 2024
d0089c0
Merge branch 'develop' into permhash
moonpatel Apr 18, 2024
bee6b79
fix
moonpatel Apr 18, 2024
e48c16b
Merge branch 'develop' into permhash
moonpatel Apr 24, 2024
c453bac
Merge branch 'develop' into permhash
moonpatel May 2, 2024
b315469
Merge branch 'develop' of github.com:intelowlproject/IntelOwl into mp…
mlodic May 10, 2024
6ac3370
migration
mlodic May 10, 2024
0d2f470
Merge branch 'develop' of github.com:intelowlproject/IntelOwl into mp…
mlodic May 10, 2024
3e81579
migrations
mlodic May 10, 2024
54d58eb
migrations
mlodic May 10, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
63 changes: 63 additions & 0 deletions api_app/analyzers_manager/file_analyzers/perm_hash.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
# This file is a part of IntelOwl https://github.com/intelowlproject/IntelOwl
# See the file 'LICENSE' for copying permission.

import logging

import magic
from permhash.functions import (
APK_MANIFEST_MIMETYPES,
APK_MIMETYPES,
CRX_MANIFEST_MIMETYPES,
CRX_MIMETYPES,
permhash_apk,
permhash_apk_manifest,
permhash_crx,
permhash_crx_manifest,
)

from api_app.analyzers_manager.classes import FileAnalyzer
from api_app.analyzers_manager.exceptions import AnalyzerRunException

logger = logging.getLogger(__name__)


class Permhash(FileAnalyzer):
"""
Create permissions hash of APK, Chrome extensions,
Android manifest and Chrome extension manifest files.
"""

def run(self):
result = {}
mimetype = magic.from_file(self.filepath, mime=True)

hash_val = ""

if mimetype in APK_MIMETYPES:
hash_val = permhash_apk(self.filepath)
elif mimetype in APK_MANIFEST_MIMETYPES:
hash_val = permhash_apk_manifest(self.filepath)
elif mimetype in CRX_MIMETYPES:
hash_val = permhash_crx(self.filepath)
elif mimetype in CRX_MANIFEST_MIMETYPES:
hash_val = permhash_crx_manifest(self.filepath)
else:
raise AnalyzerRunException(f"Mimetype {mimetype} not supported.")

# permhash returns False if for some reason the hash value can't be found
if hash_val:
result["hash"] = hash_val
else:
raise AnalyzerRunException("Could not find permissions in the file.")

return result

@classmethod
def update(cls) -> bool:
pass

@classmethod
def _monkeypatch(cls):
patches = []

return super()._monkeypatch(patches=patches)
Original file line number Diff line number Diff line change
@@ -0,0 +1,168 @@
# Generated by Django 4.2.11 on 2024-04-11 14:07

from django.db import migrations, models

import api_app.fields


class Migration(migrations.Migration):
dependencies = [
("analyzers_manager", "0077_analyzer_config_abusix"),
]

operations = [
migrations.AlterField(
model_name="analyzerconfig",
name="not_supported_filetypes",
field=api_app.fields.ChoiceArrayField(
base_field=models.CharField(
choices=[
("application/w-script-file", "Wscript"),
("application/javascript", "Javascript1"),
("application/x-javascript", "Javascript2"),
("text/javascript", "Javascript3"),
("application/x-vbscript", "Vb Script"),
("text/x-ms-iqy", "Iqy"),
("application/vnd.android.package-archive", "Apk"),
("application/x-dex", "Dex"),
("application/onenote", "One Note"),
("application/zip", "Zip1"),
("multipart/x-zip", "Zip2"),
("application/java-archive", "Java"),
("text/rtf", "Rtf1"),
("application/rtf", "Rtf2"),
("application/x-sharedlib", "Shared Lib"),
("application/vnd.microsoft.portable-executable", "Exe"),
("application/x-elf", "Elf"),
("application/octet-stream", "Octet"),
("application/vnd.tcpdump.pcap", "Pcap"),
("application/pdf", "Pdf"),
("text/html", "Html"),
("application/x-mspublisher", "Pub"),
("application/vnd.ms-excel.addin.macroEnabled", "Excel Macro1"),
(
"application/vnd.ms-excel.sheet.macroEnabled.12",
"Excel Macro2",
),
("application/vnd.ms-excel", "Excel1"),
("application/excel", "Excel2"),
(
"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
"Doc",
),
("application/xml", "Xml1"),
("text/xml", "Xml2"),
("application/encrypted", "Encrypted"),
("text/plain", "Plain"),
("text/csv", "Csv"),
(
"application/vnd.openxmlformats-officedocument.presentationml.presentation",
"Pptx",
),
("application/msword", "Word1"),
(
"application/vnd.openxmlformats-officedocument.wordprocessingml.document",
"Word2",
),
("application/vnd.ms-powerpoint", "Powerpoint"),
("application/vnd.ms-office", "Office"),
("application/x-binary", "Binary"),
("application/x-macbinary", "Mac1"),
("application/mac-binary", "Mac2"),
("application/x-mach-binary", "Mac3"),
("application/x-zip-compressed", "Compress1"),
("application/x-compressed", "Compress2"),
("application/vnd.ms-outlook", "Outlook"),
("message/rfc822", "Eml"),
("application/pkcs7-signature", "Pkcs7"),
("application/x-pkcs7-signature", "Xpkcs7"),
("multipart/mixed", "Mixed"),
("text/x-shellscript", "X Shellscript"),
("application/x-chrome-extension", "Crx"),
("application/json", "Json"),
],
max_length=90,
),
blank=True,
default=list,
size=None,
),
),
migrations.AlterField(
model_name="analyzerconfig",
name="supported_filetypes",
field=api_app.fields.ChoiceArrayField(
base_field=models.CharField(
choices=[
("application/w-script-file", "Wscript"),
("application/javascript", "Javascript1"),
("application/x-javascript", "Javascript2"),
("text/javascript", "Javascript3"),
("application/x-vbscript", "Vb Script"),
("text/x-ms-iqy", "Iqy"),
("application/vnd.android.package-archive", "Apk"),
("application/x-dex", "Dex"),
("application/onenote", "One Note"),
("application/zip", "Zip1"),
("multipart/x-zip", "Zip2"),
("application/java-archive", "Java"),
("text/rtf", "Rtf1"),
("application/rtf", "Rtf2"),
("application/x-sharedlib", "Shared Lib"),
("application/vnd.microsoft.portable-executable", "Exe"),
("application/x-elf", "Elf"),
("application/octet-stream", "Octet"),
("application/vnd.tcpdump.pcap", "Pcap"),
("application/pdf", "Pdf"),
("text/html", "Html"),
("application/x-mspublisher", "Pub"),
("application/vnd.ms-excel.addin.macroEnabled", "Excel Macro1"),
(
"application/vnd.ms-excel.sheet.macroEnabled.12",
"Excel Macro2",
),
("application/vnd.ms-excel", "Excel1"),
("application/excel", "Excel2"),
(
"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
"Doc",
),
("application/xml", "Xml1"),
("text/xml", "Xml2"),
("application/encrypted", "Encrypted"),
("text/plain", "Plain"),
("text/csv", "Csv"),
(
"application/vnd.openxmlformats-officedocument.presentationml.presentation",
"Pptx",
),
("application/msword", "Word1"),
(
"application/vnd.openxmlformats-officedocument.wordprocessingml.document",
"Word2",
),
("application/vnd.ms-powerpoint", "Powerpoint"),
("application/vnd.ms-office", "Office"),
("application/x-binary", "Binary"),
("application/x-macbinary", "Mac1"),
("application/mac-binary", "Mac2"),
("application/x-mach-binary", "Mac3"),
("application/x-zip-compressed", "Compress1"),
("application/x-compressed", "Compress2"),
("application/vnd.ms-outlook", "Outlook"),
("message/rfc822", "Eml"),
("application/pkcs7-signature", "Pkcs7"),
("application/x-pkcs7-signature", "Xpkcs7"),
("multipart/mixed", "Mixed"),
("text/x-shellscript", "X Shellscript"),
("application/x-chrome-extension", "Crx"),
("application/json", "Json"),
],
max_length=90,
),
blank=True,
default=list,
size=None,
),
),
]
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please write also a reverse_migrate function. That helps to recover in case of mistakes

128 changes: 128 additions & 0 deletions api_app/analyzers_manager/migrations/0079_analyzer_config_permhash.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
from django.db import migrations
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please also add this analyzer to the freely available playbook + to the static analyzer playbook

from django.db.models.fields.related_descriptors import (
ForwardManyToOneDescriptor,
ForwardOneToOneDescriptor,
ManyToManyDescriptor,
)

plugin = {
"python_module": {
"health_check_schedule": None,
"update_schedule": None,
"module": "perm_hash.Permhash",
"base_path": "api_app.analyzers_manager.file_analyzers",
},
"name": "Permhash",
"description": "create a hash of permissions in APK, Android manifest, chrome extension, chrome extension manifest files using [permhash](https://github.com/google/permhash).",
"disabled": False,
"soft_time_limit": 20,
"routing_key": "default",
"health_check_status": True,
"type": "file",
"docker_based": False,
"maximum_tlp": "RED",
"observable_supported": [],
"supported_filetypes": [
"application/vnd.android.package-archive",
"application/zip",
"application/java-archive",
"application/octet-stream",
"text/plain",
"application/x-chrome-extension",
"application/json",
],
"run_hash": False,
"run_hash_type": "",
"not_supported_filetypes": [],
"model": "analyzers_manager.AnalyzerConfig",
}

params = []

values = []


def _get_real_obj(Model, field, value):
def _get_obj(Model, other_model, value):
if isinstance(value, dict):
real_vals = {}
for key, real_val in value.items():
real_vals[key] = _get_real_obj(other_model, key, real_val)
value = other_model.objects.get_or_create(**real_vals)[0]
# it is just the primary key serialized
else:
if isinstance(value, int):
if Model.__name__ == "PluginConfig":
value = other_model.objects.get(name=plugin["name"])
else:
value = other_model.objects.get(pk=value)
else:
value = other_model.objects.get(name=value)
return value

if (
type(getattr(Model, field))
in [ForwardManyToOneDescriptor, ForwardOneToOneDescriptor]
and value
):
other_model = getattr(Model, field).get_queryset().model
value = _get_obj(Model, other_model, value)
elif type(getattr(Model, field)) in [ManyToManyDescriptor] and value:
other_model = getattr(Model, field).rel.model
value = [_get_obj(Model, other_model, val) for val in value]
return value


def _create_object(Model, data):
mtm, no_mtm = {}, {}
for field, value in data.items():
value = _get_real_obj(Model, field, value)
if type(getattr(Model, field)) is ManyToManyDescriptor:
mtm[field] = value
else:
no_mtm[field] = value
try:
o = Model.objects.get(**no_mtm)
except Model.DoesNotExist:
o = Model(**no_mtm)
o.full_clean()
o.save()
for field, value in mtm.items():
attribute = getattr(o, field)
if value is not None:
attribute.set(value)
return False
return True


def migrate(apps, schema_editor):
Parameter = apps.get_model("api_app", "Parameter")
PluginConfig = apps.get_model("api_app", "PluginConfig")
python_path = plugin.pop("model")
Model = apps.get_model(*python_path.split("."))
if not Model.objects.filter(name=plugin["name"]).exists():
exists = _create_object(Model, plugin)
if not exists:
for param in params:
_create_object(Parameter, param)
for value in values:
_create_object(PluginConfig, value)


def reverse_migrate(apps, schema_editor):
python_path = plugin.pop("model")
Model = apps.get_model(*python_path.split("."))
Model.objects.get(name=plugin["name"]).delete()


class Migration(migrations.Migration):
atomic = False
dependencies = [
("api_app", "0062_alter_parameter_python_module"),
(
"analyzers_manager",
"0078_alter_analyzerconfig_not_supported_filetypes_and_more",
),
]

operations = [migrations.RunPython(migrate, reverse_migrate)]
2 changes: 2 additions & 0 deletions api_app/analyzers_manager/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,8 @@ class MimeTypes(models.TextChoices):
XPKCS7 = "application/x-pkcs7-signature"
MIXED = "multipart/mixed"
X_SHELLSCRIPT = "text/x-shellscript"
CRX = "application/x-chrome-extension"
JSON = "application/json"

Comment on lines +87 to 89
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you are changing a model, you need to do a migration for this change too

@classmethod
def _calculate_from_filename(cls, file_name: str) -> Optional["MimeTypes"]:
Expand Down
3 changes: 3 additions & 0 deletions frontend/src/constants/jobConst.js
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,8 @@ export const FileMimeTypes = Object.freeze({
XPKCS7: "application/x-pkcs7-signature",
MIXED: "multipart/mixed",
X_SHELLSCRIPT: "text/x-shellscript",
CRX: "application/x-chrome-extension",
JSON: "application/json",
});

export const ObservableClassifications = Object.freeze({
Expand Down Expand Up @@ -179,6 +181,7 @@ export const FileExtensions = Object.freeze({
PUBLICVM: "publicvm",
ISO: "iso",
SH: "sh",
CRX: "crx",
});

export const InvalidTLD = Object.freeze({
Expand Down
1 change: 1 addition & 0 deletions requirements/project-requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ greynoise==2.1.0
XLMMacroDeobfuscator[secure]==0.2.3
thinkst-zippy==0.1.2
querycontacts==2.0.0
permhash==0.1.4.2

# this is required because XLMMacroDeobfuscator does not pin the following packages
pyxlsb2==0.0.8
Expand Down