Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: update OleID based analysis #165

Merged
merged 1 commit into from May 31, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
17 changes: 16 additions & 1 deletion app/factories/oldid.py
Expand Up @@ -20,10 +20,15 @@ def _parse_as_ole_file(self, attachment: Attachment) -> List[Detail]:
oleid = OleID(data)
file_info = f"{attachment.filename}({attachment.hash_.sha256})"
if oleid.has_vba_macros():
key = "vba_macros"
key = "vba"
description = f"{file_info} contains VBA macros."
details.append(Detail(key=key, description=description))

if oleid.has_xlm_macros():
key = "xlm"
description = f"{file_info} contains XLM macros."
details.append(Detail(key=key, description=description))

if oleid.has_flash_objects():
key = "flash"
description = f"{file_info} contains Flash objects."
Expand All @@ -34,6 +39,16 @@ def _parse_as_ole_file(self, attachment: Attachment) -> List[Detail]:
description = f"{file_info} is encrypted."
details.append(Detail(key=key, description=description))

if oleid.has_external_relationships():
key = "ext_rels"
description = f"{file_info} contains external relationships."
details.append(Detail(key=key, description=description))

if oleid.has_object_pool():
key = "ObjectPool"
description = f"{file_info} contains an ObjectPool stream."
details.append(Detail(key=key, description=description))

return details

def to_model(self) -> Verdict:
Expand Down
45 changes: 41 additions & 4 deletions app/services/oleid.py
@@ -1,9 +1,25 @@
from typing import Optional
from typing import Any, Optional

import oletools.oleid
from olefile import isOleFile


def is_truthy(v: Any) -> bool:
if v is None:
return False

if isinstance(v, bool):
return v is True

if isinstance(v, int):
return v > 0

try:
return str(v).upper() == "YES"
except Exception:
return False


class OleID:
def __init__(self, data: bytes):
self.oid: Optional[oletools.oleid.OleID] = None
Expand All @@ -17,18 +33,39 @@ def is_encrypted(self) -> bool:
return False

encrypted = self.oid.get_indicator("encrypted")
return encrypted is not None and encrypted.value is True
return is_truthy(encrypted.value)

def has_vba_macros(self) -> bool:
if self.oid is None:
return False

macros = self.oid.get_indicator("vba")
return macros is not None and macros.value == "Yes"
return is_truthy(macros.value)

def has_xlm_macros(self) -> bool:
if self.oid is None:
return False

macros = self.oid.get_indicator("xlm")
return is_truthy(macros.value)

def has_flash_objects(self) -> bool:
if self.oid is None:
return False

flash = self.oid.get_indicator("flash")
return flash is not None and flash.value > 0
return is_truthy(flash.value)

def has_external_relationships(self) -> bool:
if self.oid is None:
return False

flash = self.oid.get_indicator("ext_rels")
return is_truthy(flash.value)

def has_object_pool(self) -> bool:
if self.oid is None:
return False

flash = self.oid.get_indicator("ObjectPool")
return is_truthy(flash.value)