
Désovfuscateur source-à-source pour VBScript et VBA avec évaluation partielle
vbSparkle est un désobfuscateur Visual Basic multi-plateforme, de source à source, basé sur l'évaluation partielle et principalement dédié à l'analyse de code malveillant écrit en VBScript et en VBA (macro Office).
Il est écrit en C# natif et fournit une bibliothèque .Net Standard; il fonctionne sur Windows, Linux, macOS, etc.
L'analyse de Visual Basic Script et de VBA est effectuée grâce à la grammaire et aux analyseurs lexicaux d'ANTLR.
Install-Package vbSparkle
dotnet add package vbSparkle
Une fois que vous avez ajouté la bibliothèque vbSparkle à votre projet, il vous suffit d'appeler la fonction PrettifyEncoded de la classe statique VbPartialEvaluator :
string obfuscatedVB = "msgbox(chr(65)&chr(66)&(chr(67))"
string deobfuscated = VbPartialEvaluator.PrettifyEncoded(obfuscatedVB);
... retournera MsgBox("ABC").
Le projet joint vbSparkle.CLI est un exemple d'utilisation de vbSparkle en tant que CLI.
L'exemple actuel prend soit un chemin en argument, soit un binaire complet dans StdIn, et renvoie le résultat désobfusqué.

Le projet joint vbSparkle.Web est un exemple d'utilisation de vbSparkle dans une interface Web.

L'obfuscation de code VBScript et VBA est populaire parmi les attaquants et permet de contourner les mesures de détection, les antivirus, les pare-feu, les EDR, et rend l'analyse des malwares plus difficile.
Ainsi, il est courant de voir du VBScript obfusqué dès le tout premier stade d'une compromission de machine.
Une technique typique d'obfuscation de code VBScript consiste à encapsuler le script dans une chaîne obfusquée et à l'exécuter via la fonction Execute("...code..." function) après qu'elle a été décodée / évaluée.
Voyons un exemple :
Execute(chr( 456127/3833 ) & chr( 817650/7110 ) & chr( 759429/7671 ) & chr( 834138/7317 ) & chr( 57960/552 ) & chr( 2549-2437 ) & chr( 1078568/9298 ) & chr( 5143-5097 ) & chr( -8682+8783 ) & chr( 529-430 ) & chr( 673088/6472 ) & chr( 761682/6862 ) & chr( 302336/9448 ) & chr( 9427-9393 ) & chr( 410176/3944 ) & chr( -5271+5372 ) & chr( 796608/7376 ) & chr( 2896-2788 ) & chr( 318792/2872 ) & chr( 1076-1042 ) & vbcrlf )
Ici, l'attaquant a utilisé :
chr(CHAR_CODE) pour évaluer un caractère de chaîne (par ex. chr(65) = "A")456127/3833) pour évaluer la valeur du caractère& pour assembler tous les caractères décodésExecute(..) pour exécuter le script décodé.Si nous suivons l'exécution du script :
456127/3833 => 119chr(119) => "w"817650/7110 => 115chr(115) => "s""w" & "s" => "ws"Execute("ws.....Voici le script original :
wscript.echo "hello"
Une désobfuscation manuelle devient très difficile et chronophage sur de grands scripts.
Une technique de désobfuscation courante avec VBScript consiste simplement à remplacer la fonction Execute() par WScript.Echo(, puis à exécuter le script pour obtenir la sortie.
Cette dernière technique est simple mais présente quelques inconvénients :
Et, au moment où ce projet a démarré, il n'existait aucune alternative à ces deux techniques.
L'évaluation partielle n'est pas un concept nouveau ; elle est surtout utilisée par les compilateurs pour l'optimisation de code dans les processus de pré-compilation (par ex. https://en.wikipedia.org/wiki/Partial_evaluation).
Un évaluateur partiel lit un programme (appelé le programme sujet) ainsi que certaines des entrées de ce programme, et n'évalue que les parties du programme qui dépendent des entrées fournies. Une fois toutes ces parties évaluées, le programme restant (appelé le programme résiduel) est émis en sortie.
Par exemple, un processus de pré-compilation transformerait le code sujet suivant :
var1 = 3*3
var2 = sin(arg1)
var3 = var1 + func_xx(2 * var1 + var2)
en le code résiduel suivant :
var2 = sin(arg1)
var3 = 9 + func_xx(18 + var2)
Le code a été partiellement évalué avant la compilation, afin d'optimiser les performances.
On voit que ce processus simplifie le code et élimine les opérations inutiles. C'est intéressant car l'obfuscation masque le code en ajoutant du code et des opérations inutiles pour l'exécution du code.
Si nous inspectons notre échantillon initial, étape par étape :
456127/3833 peuvent être partiellement évaluées : aucun effet de bordchr(119) peut être partiellement évaluée : 119 est une constante, et c'est une fonction native, aucun effet de bord"w" & "s" peut être partiellement évalué : c'est une concaténation de caractères constants, aucun effet de bordExecute( a un effet de bord connu (exécution de script), elle ne sera pas évaluée, sauf si les effets de bord des fonctions peuvent être gérés / émulésUne évaluation partielle de cet échantillon donnerait :
Execute("wscript.echo ""hello""" & vbCrLf)
Et devinez quoi ? Nous venons de désobfusquer notre échantillon.
Eh bien, en pratique, c'est bien plus compliqué :
Heureusement, ANTLR est un puissant générateur d'analyseurs syntaxiques pour lire, traiter, exécuter ou traduire du texte structuré ou des fichiers binaires. Il est connu pour être largement utilisé afin de construire des langages, des outils et des frameworks. À partir d'une grammaire, ANTLR génère un analyseur syntaxique capable de construire des arbres d'analyse et génère également une interface d'écoute (listener) (ou un visiteur) qui facilite la réponse à la reconnaissance des expressions d'intérêt.
ANTLR peut générer des analyseurs lexicaux, des analyseurs syntaxiques, des analyseurs d'arbres et des analyseurs combinés lexeur-parseur. Les analyseurs syntaxiques peuvent générer automatiquement des arbres d'analyse ou des arbres de syntaxe abstraite qui peuvent ensuite être traités avec des analyseurs d'arbres. ANTLR fournit une notation unique et cohérente pour spécifier les analyseurs lexicaux, les analyseurs syntaxiques et les analyseurs d'arbres.
Par défaut, ANTLR lit une grammaire et génère un reconnaisseur pour le langage défini par la grammaire (c'est-à-dire un programme qui lit un flux d'entrée et génère une erreur si le flux d'entrée n'est pas conforme à la syntaxe spécifiée par la grammaire).