Skip to main content

No project description provided

Project description

Malin

Description

Paquet Python permettant de créer facilement de nouveaux moteurs antiviraux à intégrer dans l'environnement Malin.

Introduction

Pourquoi ce paquet ?

Malin a initialement été développé en Golang. Cependant, ce langage peut être assez niche et présenter une courbe d'apprentissage élevée. Il m'a semblé naturel de créer un paquet Python pour faciliter le développement pour les consultants, les analystes SOC, et les équipes CERT. Ce paquet a été conçu pour être le plus simple possible à utiliser.

A qui est dédié ce paquet ?

Si vous ne connaissez pas Malin, ce paquet n'est probablement pas pour vous :) En effet, il n'est pas destiné à un usage grand public. En effet, sans l'environnement Malin comprenant l'ordonnanceur, les workers, etc., ce paquet ne sera pas très utile, car il a été développé pour un usage très spécifique.

Usage

Comme j'aime bien les exemples et que je pense que c'est plus sympa d'apprendre avec des exemples, je vais vous décrire l'utilisation du paquet pas à pas.

Quick Start

Installation

Avant de plonger dans le code, il faut d'abord installer le paquet. Rien de plus simple :

pip install malin

Une fois cela fait, vous avez accompli la partie la plus difficile ;)

Boilerplate Code

Concernant le code, voici le code de base à utiliser :

from malin import Malin, ScanSummary

def parser(engineResult) -> ScanSummary:
    # Parser le résultat de l'engine et le convertir en ScanSummary

def engine(filename: str) -> str:
    # Lancer l'engine avec le nom de fichier reçu depuis le worker
    # Renvoyer le résultat pour qu'il soit passé au parser

malinEngine = Malin(engine, parser)
malinEngine.run(hots="0.0.0.0", port=5000) # On peut specifier les champs host et port

La classe Malin expose une API avec les bons endpoints et méthodes pour que le worker puisse envoyer et recevoir les rapports d'analyse. La seule partie non générique est :

  • Comment lancer et récupérer le résultat d'un moteur
  • Comment parser la reponse de l'engine

En effet, les éditeurs d'antivirus n'ont pas uniformisé l'usage de leurs moteurs ni leurs sorties :| Cela dépend donc de chaque moteur. C'est pourquoi il est demandé de coder deux fonctions :

  • engine: Cette fonction lance l'analyse avec le moteur, récupère la sortie et la retourne pour qu'elle soit envoyée au parser.
  • parser: Cette fonction parse la sortie de la fonction engine et la convertit en ScanSummary

La class ScanSummary est definie comme suit:

@dataclass
class ScanSummary:
    engine: str
    message: str
    detected: bool
    malware: List[str]

Error handling

Parfois, les choses ne se passent pas comme prévu (mdr, tout le temps). Il est possible de renvoyer des erreurs prédéfinies telles que :

  • InvalidOutput : Peut être levée dans la fonction parser quand les règles de parsing ne sont pas respectées. Par exemple, si le binaire lancé n'est pas le bon ou qu'il y a une erreur dans le rapport fourni.

Exemple concret:

Maintenant que vous êtes devenus des pros (eh oui, on n'a pas de temps à perdre ici), nous allons voir comment implémenter un moteur antiviral peu connu, "Windows Defender" :)

Pour interagir avec "Windows Defender", on peut appeler le binaire MpCmdRun.exe avec les bonnes options. Comme ce tutoriel vise à vous familiariser avec le paquet malin et non à expliquer comment utiliser "MpCmdRun.exe", nous allons utiliser un wrapper pour "Windows Defender" appelé pyrattle (petite promo). Vous pourriez aussi l'implémenter différemment (avec os.system par exemple), c'est vous qui voyez ;)

Engine

Commençons par la partie engine. Il suffit de lancer l'analyse du fichier donné en paramètre (filename) et de retourner le résultat obtenu. À noter : Le type de la valeur de retour n'est pas très important. Tant que la fonction parser gère le type retourné, ça fonctionne. Dans notre cas, nous retournons une instance de ScanResult, mais nous aurions très bien pu retourner un str :

from pyrattle import PyDefender
from pyrattle.pyrattle import ScanType, ScanResult

from malin import Malin
#...
def defenderEngine(filename: str) :
    scanner = PyDefender()
    result : ScanResult = scanner.scan(scan_type=ScanType.CUSTOM ,file=filename, disable_remediation=True)
    return result

Parser

Maintenant, la partie la plus difficile (c'est faux XD). Puisque l'engine retourne un ScanResult, la fonction parser doit prendre en argument un ScanResult. Tout ce qu'on fait ici, c'est convertir le résultat en ScanSummary et adapter le message.

from malin import Malin, ScanSummary

# ...

def defenderParser(output: ScanResult) -> ScanSummary:
    message: str = "Malware Detected"
    if (not output.is_threat):
       message = "Malware not Detected" 

    result = ScanSummary(engine="Windows Defender", message=message, detected=output.is_threat, malware=[output.threat])
    
    return result 

Code final

En réunissant les fonctions précédentes, on obtient le code final :

from pyrattle import PyDefender
from pyrattle.pyrattle import ScanType, ScanResult

from malin import Malin, ScanSummary

def defenderParser(output: ScanResult) -> ScanSummary:
    message: str = "Malware Detected"
    if (not output.is_threat):
       message = "Malware not Detected" 

    result = ScanSummary(engine="Windows Defender", message=message, detected=output.is_threat, malware=[output.threat])
    
    return result 

def defenderEngine(filename: str) :
    scanner = PyDefender()
    result : ScanResult = scanner.scan(scan_type=ScanType.CUSTOM ,file=filename, disable_remediation=True)
    return result

malinDefender = Malin(defenderEngine, defenderParser)
malinDefender.run(host="0.0.0.0")

Licence

Ce projet est sous licence MIT. Consultez le fichier LICENSE pour plus d'informations.

Author

Yassine Damiri https://damiri.fr https://github.com/Yasha-ops

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

malin-0.2.1.tar.gz (8.7 kB view details)

Uploaded Source

Built Distribution

malin-0.2.1-py3-none-any.whl (10.5 kB view details)

Uploaded Python 3

File details

Details for the file malin-0.2.1.tar.gz.

File metadata

  • Download URL: malin-0.2.1.tar.gz
  • Upload date:
  • Size: 8.7 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: poetry/1.8.3 CPython/3.12.3 Windows/10

File hashes

Hashes for malin-0.2.1.tar.gz
Algorithm Hash digest
SHA256 be2cbdc57b474cb5a0dfb675a74c6877791ea6eedb9323d338f75e3d712a7e88
MD5 8f795309debd4a55714fe5d88bb85ff4
BLAKE2b-256 3ebfead48102f6c7c87c5be353c7259579f6ea51090d32f5aa11c0ad13c6517c

See more details on using hashes here.

File details

Details for the file malin-0.2.1-py3-none-any.whl.

File metadata

  • Download URL: malin-0.2.1-py3-none-any.whl
  • Upload date:
  • Size: 10.5 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: poetry/1.8.3 CPython/3.12.3 Windows/10

File hashes

Hashes for malin-0.2.1-py3-none-any.whl
Algorithm Hash digest
SHA256 44f42a55715a4cfa1cf57f29b7e80895d920556ea8f116e3fc85be735287d9ff
MD5 6a67d2802ddf898258da57f644e90e02
BLAKE2b-256 6a947527e56cc3fdb07181b664d45733a321471029947d0b9e4d675a0d1aedef

See more details on using hashes here.

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page