Skip to content

Commit

Permalink
Introduce new hashing and imrpove output (#15)
Browse files Browse the repository at this point in the history
- Introduce SHA1 and SHA256
- Upgrade dependencies
- Make output more readable
  • Loading branch information
vojtechjelinek authored Oct 1, 2024
1 parent 0220221 commit a787d22
Show file tree
Hide file tree
Showing 15 changed files with 120 additions and 85 deletions.
23 changes: 21 additions & 2 deletions maldump/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
if TYPE_CHECKING:
from maldump.structures import Quarantine

__version__ = "0.4.0"
__version__ = "0.5.0"


def main() -> None:
Expand Down Expand Up @@ -68,6 +68,8 @@ def export_files(
tar.close()
if total > 0:
print(f"Exported {total} object(s) into '{out_file}'")
else:
print("No quarantined files found!")


def export_meta(
Expand All @@ -82,22 +84,39 @@ def export_meta(
if len(entries) > 0:
csv_path = dest.joinpath(meta_file)
with open(csv_path, "w", encoding="utf-8", newline="") as f:
fields = ["timestamp", "antivirus", "threat", "path", "size", "md5"]
fields = [
"timestamp",
"antivirus",
"threat",
"path",
"size",
"md5",
"sha1",
"sha256",
]
writer = csv.DictWriter(f, fields, extrasaction="ignore")
writer.writeheader()
writer.writerows(entries)
print(f"Written {len(entries)} row(s) into file '{meta_file}'")
else:
print(
f"The file '{meta_file}' wasn't created as there is nothing in quarantine"
)


def list_files(avs: list[Quarantine]) -> None:
quarantined_file_exists = False
for i, av in enumerate(avs):
entries = av.export()
if len(entries) > 0:
quarantined_file_exists = True
if i != 0:
print()
print(Fore.YELLOW + "---", av.name, "---" + Style.RESET_ALL)
for e in entries:
print(e.path)
if not quarantined_file_exists:
print("No quarantined files found!")


def parse_cli() -> argparse.Namespace:
Expand Down
3 changes: 0 additions & 3 deletions maldump/parsers/avast_parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
import sqlite3
import tempfile
from datetime import datetime as dt
from hashlib import md5
from os import unlink
from typing import TYPE_CHECKING

Expand Down Expand Up @@ -85,8 +84,6 @@ def get(e, f) -> str:
q.timestamp = dt.fromtimestamp(int(get(e, "TransferTime")))
q.threat = get(e, "Virus")
q.path = path
q.size = len(malfile)
q.md5 = md5(malfile).hexdigest()
q.malfile = malfile

quarfiles.append(q)
Expand Down
3 changes: 0 additions & 3 deletions maldump/parsers/avg_parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
import sqlite3
import tempfile
from datetime import datetime as dt
from hashlib import md5
from os import unlink
from typing import TYPE_CHECKING

Expand Down Expand Up @@ -85,8 +84,6 @@ def get(e, f):
q.timestamp = dt.fromtimestamp(int(get(e, "TransferTime")))
q.threat = get(e, "Virus")
q.path = path
q.size = len(malfile)
q.md5 = md5(malfile).hexdigest()
q.malfile = malfile

quarfiles.append(q)
Expand Down
3 changes: 0 additions & 3 deletions maldump/parsers/avira_parser.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
from __future__ import annotations

from datetime import datetime as dt
from hashlib import md5
from typing import TYPE_CHECKING

from maldump.parsers.kaitai.avira_parser import AviraParser as KaitaiParser
Expand All @@ -23,8 +22,6 @@ def from_file(self, name: str, location: Path) -> list[QuarEntry]:
q.timestamp = dt.fromtimestamp(kt.qua_time)
q.threat = kt.mal_type
q.path = kt.filename[4:]
q.size = len(kt.mal_file)
q.md5 = md5(kt.mal_file).hexdigest()
q.malfile = kt.mal_file
quarfiles.append(q)
kt.close()
Expand Down
3 changes: 0 additions & 3 deletions maldump/parsers/eset_parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@
import struct
import sys
from datetime import datetime
from hashlib import md5
from pathlib import Path

from maldump.structures import QuarEntry
Expand Down Expand Up @@ -202,8 +201,6 @@ def from_file(self, name: str, location: Path) -> list[QuarEntry]:
q.threat = metadata["infiltration"]
q.path = metadata["obj"]
q.malfile = self._get_malfile(metadata["user"], metadata["objhash"])
q.size = len(q.malfile)
q.md5 = md5(q.malfile).hexdigest()
quarfiles.append(q)

return quarfiles
2 changes: 0 additions & 2 deletions maldump/parsers/forticlient_parser.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
from __future__ import annotations

from datetime import datetime as dt
from hashlib import md5
from typing import TYPE_CHECKING

from maldump.parsers.kaitai.forticlient_parser import ForticlientParser as KaitaiParser
Expand Down Expand Up @@ -32,7 +31,6 @@ def from_file(self, name: str, location: Path) -> list[QuarEntry]:
q.threat = kt.mal_type
q.path = self._normalize_path(kt.mal_path)
q.size = kt.mal_len
q.md5 = md5(kt.mal_file).hexdigest()
q.malfile = kt.mal_file
quarfiles.append(q)
kt.close()
Expand Down
2 changes: 0 additions & 2 deletions maldump/parsers/gdata_parser.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
from __future__ import annotations

from datetime import datetime as dt
from hashlib import md5
from typing import TYPE_CHECKING

from maldump.parsers.kaitai.gdata_parser import GdataParser as KaitaiParser
Expand All @@ -25,7 +24,6 @@ def from_file(self, name: str, location: Path) -> list[QuarEntry]:
q.threat = kt.data1.malwaretype.string_content
q.path = kt.data2.path.string_content[4:]
q.size = kt.data2.filesize
q.md5 = md5(kt.mal_file).hexdigest()
q.malfile = kt.mal_file
quarfiles.append(q)
kt.close()
Expand Down
2 changes: 0 additions & 2 deletions maldump/parsers/kaspersky_parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

import sqlite3
from datetime import datetime
from hashlib import md5
from typing import TYPE_CHECKING

from maldump.structures import QuarEntry
Expand Down Expand Up @@ -49,7 +48,6 @@ def from_file(self, name: str, location: Path) -> list[QuarEntry]:
q.threat = row[3]
q.path = row[1] + row[2]
q.size = row[7]
q.md5 = md5(malfile).hexdigest()
q.malfile = malfile
quarfiles.append(q)

Expand Down
1 change: 0 additions & 1 deletion maldump/parsers/malwarebytes_parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,6 @@ def from_file(self, name: str, location: Path) -> list[QuarEntry]:
q.timestamp = self._normalize_time(metadata["trace"]["cleanTime"])
q.threat = metadata["threatName"]
q.path = metadata["trace"]["objectPath"]
q.size = len(malfile)
q.md5 = metadata["trace"]["objectMD5"].lower()
q.malfile = malfile
quarfiles.append(q)
Expand Down
2 changes: 0 additions & 2 deletions maldump/parsers/mcafee_parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
import sys
import zipfile
from datetime import datetime as dt
from hashlib import md5
from typing import TYPE_CHECKING, TypedDict
from zipfile import ZipFile

Expand Down Expand Up @@ -45,7 +44,6 @@ def from_file(self, name: str, location: Path) -> list[QuarEntry]:
q.threat = parser["threat"]
q.path = parser["file_name"]
q.size = int(parser["size"])
q.md5 = md5(parser["mal_file"]).hexdigest()
q.malfile = parser["mal_file"]
quarfiles.append(q)

Expand Down
3 changes: 0 additions & 3 deletions maldump/parsers/windef_parser.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
from __future__ import annotations

from datetime import datetime as dt
from hashlib import md5
from typing import TYPE_CHECKING

from maldump.parsers.kaitai.windef_entries import WindefEntries as KaitaiParserEntries
Expand Down Expand Up @@ -47,8 +46,6 @@ def from_file(self, name: str, location: Path) -> list[QuarEntry]:
q.timestamp = ts
q.threat = kt.data1.mal_type
q.path = self._normalize(e.entry.path.character)
q.size = len(malfile)
q.md5 = md5(malfile).hexdigest()
q.malfile = malfile
quarfiles.append(q)
kt.close()
Expand Down
39 changes: 33 additions & 6 deletions maldump/structures.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
from __future__ import annotations

import hashlib
from abc import ABC, abstractmethod
from typing import TYPE_CHECKING

Expand All @@ -12,12 +13,41 @@ class QuarEntry:
timestamp: dt
threat: str
path: str
size: int
md5: str
malfile: bytes
size: int | None = None
_md5: str | None = None
sha1: str | None = None
sha256: str | None = None
_malfile: bytes

def __init__(self) -> None: ...

@property
def malfile(self) -> bytes:
return self._malfile

@malfile.setter
def malfile(self, value: bytes) -> None:
self._malfile = value
if self._md5 is None:
self._md5 = hashlib.md5(value).hexdigest()
if self.sha1 is None:
self.sha1 = hashlib.sha1(value).hexdigest()
if self.sha256 is None:
self.sha256 = hashlib.sha256(value).hexdigest()
if self.size is None:
self.size = len(value)

@property
def md5(self) -> str:
if self._md5 is None:
err_msg = "MD5 hash needs to be set"
raise ValueError(err_msg)
return self._md5

@md5.setter
def md5(self, value: str) -> None:
self._md5 = value


class Quarantine(ABC):
"""Abstract class describing quarantines"""
Expand All @@ -27,9 +57,6 @@ class Quarantine(ABC):
# Absolute location of the quarantine folder
location: Path

@abstractmethod
def __init__(self) -> None: ...

@abstractmethod
def export(self) -> list[QuarEntry]: ...

Expand Down
Loading

0 comments on commit a787d22

Please sign in to comment.