Utiliser l’API de VirusTotal avec C++Builder

VirusTotal est un service gratuit qui permet la détection de virus, vers, chevaux de Troie ou tout autre type de programme malveillant. En visitant le site web de cette application, il est possible de choisir un fichier sur votre disque dur et de le soumettre à une analyse. Par la suite, plusieurs antivirus vérifieront si les données comportent des partie suspectes. Le résultat sera ensuite disponible en ligne.

Cet outil web est vraiment génial, mais ce qui l’est encore plus c’est qu’il existe une interface API publique que l’on peut utiliser avec des requêtes POST par HTTP. Les réponses seront en format JSON (JavaScript Object Notation).

Avant de commencer, il faudra vous inscrire pour obtenir une clef d’API. Elle sera affichée dans la section API de votre profil. Il est à noter qu’avec cette clef vous ne pourrez effectuer que quatre requêtes par minute.

Maintenant, on peut commencer à coder. La première étape est de créer un nouveau projet FireMonkey HD. Dans la Form, il faut insérer un TIdHTTP, un TIdSSLIOHandlerSocketOpenSSL, un TOpenDialog, un contrôle TEdit deux TButton et un TMemo.

Je vous propose de placer les composants dans la fenêtre de la manière suivante:
VirusTotal API

Vous pourrez aussi utiliser des textes similaires à ceux de l’image pour les différents contrôles.

Dans votre fichier cpp voici la liste de fichiers d’en-tête à utiliser ainsi que la macro qui va contenir votre clef d’API. N’essayez pas d’utiliser celle-ci, il s’agit de caractères écrits de façon aléatoire.

#define APIKEY "g9898984d0909534e1230958567f098090928712a8034cb0809786201854f678"
#include <Data.DBXJSON.hpp>
#include <Idmultipartformdata.hpp>

Voici le code à ajouter dans votre constructeur:

    IdHTTP1->IOHandler = IdSSLIOHandlerSocketOpenSSL1;

    OpenDialog1->Filter = "Application (*.exe)|*.EXE|Tous les fichiers|*.*";
    OpenDialog1->Options = System::Uitypes::TOpenOptions()
        << TOpenOption::ofHideReadOnly << TOpenOption::ofEnableSizing <<
        TOpenOption::ofFileMustExist;

Étant donné que nous accéderons à un site web qui utilise SSL (https), la première ligne de code est critique. Parce que nous utilisons OpenSSL, les fichiers ssleay32.dll et libeay32.dll devront être distribués avec votre application.

La prochaine étape est d’ajouter le code dans l’événement Button1Click.

    if(OpenDialog1->Execute() == false)
    {
        return;
    }

    Idmultipartformdata::TIdMultiPartFormDataStream* Params =
        new Idmultipartformdata::TIdMultiPartFormDataStream();
    Params->AddFormField("apikey", APIKEY);
    Params->AddFile("file", OpenDialog1->FileName, "application/octet-stream");

    System::UnicodeString Response = IdHTTP1->Post(
        "https://www.virustotal.com/vtapi/v2/file/scan", Params);

    TJSONObject* Obj = static_cast<TJSONObject*>
        (TJSONObject::ParseJSONValue(Response));
    if(Obj)
    {
        TJSONPair* Pair;
        TJSONString* Answer;
        if((Pair = Obj->Get("response_code")) != NULL)
        {
            Answer = static_cast<TJSONString*>(Pair->JsonValue);
            if(Answer->ToString() == "1")
            {
                if((Pair = Obj->Get("resource")) != NULL)
                {
                    Answer = static_cast<TJSONString*>(Pair->JsonValue);
                    Edit1->Text = AnsiDequotedStr(Answer->ToString(), '\"');
                }
            }
            else
            {
                Edit1->Text = "Erreur";
            }
        }
    }

    delete Params;

Ce code est utilisé pour la soumission du fichier choisi avec le TOpenDialog vers le serveur de VirusTotal. Si le code de la réponse est 1, ce qui signifie donc que la requête à réussi, la ressource sera affichée dans le TEdit.

Finalement, il faut ajouter ce code dans l’événement Button2Click.

    Idmultipartformdata::TIdMultiPartFormDataStream* Params =
        new Idmultipartformdata::TIdMultiPartFormDataStream();
    Params->AddFormField("apikey", APIKEY);
    Params->AddFormField("resource", Edit1->Text);

    System::UnicodeString Response = IdHTTP1->Post(
        "https://www.virustotal.com/vtapi/v2/file/report", Params);

    TJSONObject* Obj = static_cast<TJSONObject*>
        (TJSONObject::ParseJSONValue(Response));
    if(Obj)
    {
        TJSONPair* Pair = Obj->Get("scans");;
        if(Pair)
        {
            TJSONObject* Scans = static_cast<TJSONObject*>(Pair->JsonValue);
            TJSONPairEnumerator* Enumerator = Scans->GetEnumerator();
            while(Enumerator->MoveNext())
            {
                String AntivirusName =
                    AnsiDequotedStr(Enumerator->Current->JsonString->ToString(), '\"');
                Memo1->Lines->Add(AntivirusName);

                TJSONObject* AntivirusData =
                    static_cast<TJSONObject*>(Enumerator->Current->JsonValue);

                String Value;
                TJSONString* Answer;
                if((Pair = AntivirusData->Get("detected")) != NULL)
                {
                    Answer = static_cast<TJSONString*>(Pair->JsonValue);
                    Value = AnsiDequotedStr(Answer->ToString(), '\"');
                    Memo1->Lines->Add("   Detected: " + Value);
                }
                if((Pair = AntivirusData->Get("version")) != NULL)
                {
                    Answer = static_cast<TJSONString*>(Pair->JsonValue);
                    Value = AnsiDequotedStr(Answer->ToString(), '\"');
                    Memo1->Lines->Add("   Version: " + Value);
                }
                if((Pair = AntivirusData->Get("result")) != NULL)
                {
                    Answer = static_cast<TJSONString*>(Pair->JsonValue);
                    Value = AnsiDequotedStr(Answer->ToString(), '\"');
                    Memo1->Lines->Add("   Result: " + Value);
                }
                if((Pair = AntivirusData->Get("update")) != NULL)
                {
                    Answer = static_cast<TJSONString*>(Pair->JsonValue);
                    Value = AnsiDequotedStr(Answer->ToString(), '\"');
                    Memo1->Lines->Add("   Update: " + Value);
                }
            }
        }
    }
    delete Params;

Cette méthode servira à aller chercher le résultat d’une analyse pour la ressource entrée dans le TEdit. Le tout sera affiché dans le contrôle TMemo.

Il est important de savoir que les fichiers soumis par l’API ont la priorité d’analyse la plus basse. Dépendant de la charge de travail de VirusTotal, il pourrait être possible d’attendre plusieurs heures avant que le fichier soit analysé. Il est donc important d’appeler ce code à intervalle régulier pour s’assurer que tous les résultats sont disponibles.

La réponse de la requête POST ressemble à ceci:

{
   "scans":{
      "AVG":{
         "detected":false,
         "version":"10.0.0.1190",
         "result":null,
         "update":"20120826"
      },
      "Panda":{
         "detected":false,
         "version":"10.0.3.5",
         "result":null,
         "update":"20120826"
      }
   },
   "scan_id":"51a16f4a4cd8089b559a9fe694c6ac67eb0d4ad05ef564b797e5e8caf3c18813-1346036118",
   "sha1":"189f6287cd36c2f49bc828a556a70d960b7547b3",
   "resource":"51a16f4a4cd8089b559a9fe694c6ac67eb0d4ad05ef564b797e5e8caf3c18813",
   "response_code":1,
   "scan_date":"2012-08-27 02:55:18",
   "permalink":"https://www.virustotal.com/file/51a16f4a4cd8089b559a9fe694c6ac67eb0d4ad05ef564b797e5e8caf3c18813/analysis/1346036118/",
   "verbose_msg":"Scan finished, scan information embedded in this object",
   "total":2,
   "positives":0,
   "sha256":"51a16f4a4cd8089b559a9fe694c6ac67eb0d4ad05ef564b797e5e8caf3c18813",
   "md5":"463b0fe60365c7cc84325646aabeb907"
}

Pour plus de détail sur l’API vous pouvez consulter la page web suivante: https://www.virustotal.com/documentation/public-api

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *

*