[Expert] Désobfuscation d'un JavaScript malveillant avec Vim

La compromission d’une machine débute souvent par l’exécution d’un script malveillant ayant pour rôle de télécharger une charge finale (ransomware, malware bancaire, etc…). Pour nombre de ces scripts, l’unique fonctionnalité réside dans le téléchargement de cette charge. Au cours d’une mission de réponse à incident, le CSIRT Orange Cyberdefense a constaté l’emploi d’un script plus original incorporant les fonctionnalités d’un vers ; en se propageant sur les disques réseaux et les disques amovibles connectés à la machine infectée, ce dernier a permis à la charge malveillante finale (le malware bancaire Gootkit) de réaliser des mouvements latéraux au sein du réseau compromis et d’infecter plusieurs dizaines de machines.

Cet article, qui se veut didactique, vise à illustrer le processus de désobfuscation de ce script malveillant en utilisant les fonctionnalités de recherche et de remplacement d’expressions régulières fournies par l’éditeur de texte Vim, et à présenter les principales fonctionnalités du code désobfusqué. Le script est disponible sur VirusTotal (sha256 : eb60b608bed639d5111adee68addfd5815f1e5c109a0e03a109f808eb77875d0).

Cheat sheets : désobfuscation avec Vim

La complexité de l’obfuscation d’un script malveillant varie selon les cas : dans certains le processus de désobfuscation nécessite la mise au point d’outils spécifiques (un script Python par exemple), dans d’autres un (bon) éditeur de texte et quelques expressions régulières suffisent à retrouver le code original. Pour le script qui nous intéresse ici, la désobfuscation a été réalisée en combinant les expressions, commandes et fonctions Vim présentées ci-dessous.

Expressions utilisées

Expression

Catégorie

Cible

Exemple d’expression

Exemple de cible

[a-z]

Caractères

Caractère minuscule compris dans une gamme donnée

[a-e]

a1fe

[a-zA-Z0-9]

Caractères

Caractère minuscule, majuscule ou chiffre compris dans une gamme donnée

[a-e0-3]

a1f4

[^a-z]

Caractères

Caractère non compris dans une gamme donnée

[^a-e]

 

ab1fe

\d

Caractères

Caractère correspondant à un chiffre en base décimale

\d

ab1c9

\x

Caractères

Caractère correspondant à un chiffre en base hexadécimale

\x

__bter5

\+

Quantificateurs

Au moins un des élément précédant le quantificateur

[a-z]\+

ab1z

\{3}

Quantificateurs

Exactement 3 des éléments précédant le quantificateur

[a-z]\{3}

ab12cde345def

\(\)

Logique

Sous-groupe au sein d’un pattern

[a-z]_\([0-9]\)

utilisée avec submatch() ou :%s (voir ci-dessous)


Commandes Vim utilisées

Commande

Fonction

Exemple

Effet

/

Recherche un pattern

/[a-z]

Recherche toutes les lettres en minuscule

:%s/a/b/c

Remplace l’élément a par l’élément b (c = option)

:%s/[a-z]/0/g

Remplace toutes les lettres en minuscule par 0 (option g = tout le document)

\=

Évalue une expression

:%s/[a-z]/\=nr2char(0x30)/g

Idem

 

Fonctions Vim utilisées

Fonction

Définition

str2nr(a, b)

Convertit la chaine de caractères a en un entier de base b

nr2char(a)

Convertit le code a d’un caractère en son caractère correspondant

submatch(a)

Fait référence au sous-groupe d’index a au sein d’une expression

 

Désobfuscation du script

Du JavaScript encodé au JavaScript obfusqué

Le script malveillant se présente au format .jse (JavaScript encoded). Il s’agit d’un format de fichier développé par Microsoft dans l’objectif de rendre le code original d’un fichier JavaScript illisible. Ce format de fichier, initialement mis au point pour les développeurs qui souhaitaient protéger leur code des regards indiscrets, a rapidement été adopté par les auteurs de malwares. Les fichiers *.jse peuvent être décodé en utilisant l’outil Windows Script Decoder. Nous obtenons en sortie un fichier JavaScript décodé qu’il faut maintenant désobfusquer (figure 1).

 

Thumbnail

Figure 1 : Script encodé (en haut), utilisation du décodeur (milieu) et script décodé (en bas)

 

1er pattern d’obfuscation : codes Unicode

La première technique d’obfuscation consiste à remplacer certains caractères par la valeur hexadécimale de leur code Unicode (figure 2).

 

Thumbnail

Figure 2 : Premier pattern d’obfuscation

 

Par exemple, le nom de la variable WshShell peut être obfusqué de la manière suivante :

var \u0057\u0073\u0068\u0053\u0068\u0065\u006c\u006c

L’expression régulière correspondant à ce pattern d’obfuscation est la suivante :

L’antislash est interprété, par défaut, comme le début d’une commande. Si nous voulons chercher ce caractère en tant que tel, il doit être précédé d’un antislash; ainsi, \\u correspond à la chaine de caractères \u. Nous cherchons ensuite quatre hexadécimaux : \x permet de trouver un chiffre exprimé en base hexadécimale (0-f), et le quantificateur \{4} signifie exactement 4. L’accolade ouvrante est précédée d’un antislash pour indiquer le début d’une commande. Les parenthèses (précédées d’un antislash) permettent de délimiter un sous-pattern au sein de notre expression, auquel nous pouvons faire référence par la suite grâce à la fonction submatch().

Désobfuscation du pattern 1

La désobfuscation de ce premier pattern peut être réalisée avec la commande suivante :

:%s/\\u\(\x\{4}\)/\=nr2char(str2nr(submatch(1),16))/g

  • Nous retrouvons en premier paramètre le pattern recherché (\\u\(\x\{4}\)).
  • Le second paramètre est le résultat de l’évaluation (\=) de l’expression nr2char(str2nr(submatch(1),16)) :
    • la fonction submatch() référence la suite de 4 hexadécimaux du premier paramètre (\(\x\{4}\))
    • la fonction str2nr() les convertit en un entier de base 16
    • la fonction nr2char() convertit cet entier -qui correspond à un code caractère- en son caractère correspondant.
  • L’option g (pour global) signifie que la commande est appliquée dans l’ensemble du document.

 

2ème pattern d’obfuscation : objets anonymes et couples clé / valeur

La deuxième technique d’obfuscation consiste à obfusquer un caractère en l’assignant comme valeur d’une clé (figure 3), et est à la base de la quasi-totalité des patterns qui seront présentés par la suite.

 

Figure 3 : pattern d’obfuscation basé sur des couples clé / valeur

Par exemple, le caractère t peut être obfusqué de la manière suivante :

{key1:'t',key2:value2}.key1

  • Un objet anonyme ({...}) contenant 2 couples clé / valeur (key1:'t' et key2:value2) est créé
  • La valeur de la première clé est utilisée ({...}.key1)

Ce pattern peut également servir à obfusquer tout ou partie d’une chaine de caractères en effectuant des concaténations. Par exemple, la chaine foo peut être obfusquée de la manière suivante :

{key1 :'f',key2:value2}.key1+{key3 :'o',key4:value4}.key3+{key5 :'o',key6:value6}.key5

La désobfuscation de ce pattern se fait à l’aide de 3 expressions régulières, très proches, qui permettent de conserver les guillemets de début et de fin de chaine. Toutes seront les variantes d’un même pattern générique auquel nous ajouterons des préfixes et / ou suffixes afin de distinguer début, milieu et fin de chaine. Pour que la désobfuscation fonctionne, il faut suivre l’ordre suivant : début de chaine, fin de chaine et milieu de chaine.

Construction du pattern générique

L’examen du code obfusqué permet d’établir que _[a-zA-Z]\+\d*_\d est une expression possible pour trouver les clés des premiers couples clé / valeur de chaque objet anonyme (cf. figure 3) :

  • _ le nom de la clé commence par le caractère underscore,
  • [a-zA-Z]\+ suivi d’au moins une lettre de l’alphabet,
  • \d* suivie de 0 ou plus décimal,
  • _ suivi d’un second caractère underscore,
  • \d suivi d’un seul décimal.

L’examen du code révèle également que c’est toujours la première clé de l’objet anonyme qui est utilisée ({…}.key1) ; le caractère obfusqué peut être récupéré avec l’expression \(.\) :

  • . signifie n’importe quel caractère
  • \(\) permet de référencer un sous-groupe contenant ce caractère et de le récupérer par la suite

L’expression permettant de trouver les clés des seconds couples clé / valeur est très proche de la première : _[a-zA-Z]\+_\d. Les valeurs associées aux secondes clés, enfin, sont toujours composées d’au moins un décimal : \d\+.

En mettant tous ces éléments bout à bout, nous pouvons établir le pattern générique à partir duquel nous construirons nos 3 expressions régulières :

{_[a-zA-Z]\+\d*_\d:'\(.\)',_[a-zA-Z]\+_\d:'\d\+'}\._[a-zA-Z]\+\d*_\d

Note : dans cette expression régulière, le point . signifie n’importe quel caractère ; pour rechercher le caractère . en tant que tel, il faut le faire précéder d’un antislash.

Début de chaine

Globalement, le début d’une chaine de caractères ne peut être précédé du caractère + car ce dernier sert aux concaténations ; en préfixant notre pattern générique avec [^+], nous pouvons trouver tous les débuts de chaine. Lors de la désobfuscation, il faudra néanmoins préserver le caractère ([, =, etc…) précédant l’accolade { ; pour cela, le préfixe [^+] est intégré dans un sous-groupe : \([^+]\).

Pattern de début de chaine :

\([^+]\){_[a-zA-Z]\+\d*_\d:'\(.\)',_[a-zA-Z]\+_\d:'\d\+'}\._[a-zA-Z]\+\d*_\d

Fin de chaine

Le pattern générique, s’il se trouve en fin de chaine, sera toujours précédé du caractère + et suivi de l’un de ces 4 caractères : , ou ; ou ) ou ]. Ces 4 derniers caractères doivent être mis entre crochet [] pour indiquer que nous cherchons parmi une gamme. Là encore, un sous-groupe est nécessaire afin de les préserver lors de la désobfuscation, ce qui nous donne le suffixe \([,;)\]]\). Noter que le premier caractère ] est précédé d’un antislash pour indiquer qu’il s’agit du caractère en tant que tel et non d’un élément d’une commande.

Pattern de fin de chaine :

+{_[a-zA-Z]\+\d*_\d:'\(.\)',_[a-zA-Z]\+_\d:'\d\+'}\._[a-zA-Z]\+\d*_\d\([,;)\]]\)

Milieu de chaine

Le pattern générique, s’il obfusque des caractères situés en milieu de chaine, sera précédé du caractère +.

Pattern de milieu de chaine :

+{_[a-zA-Z]\+\d*_\d:'\(.\)',_[a-zA-Z]\+_\d:'\d\+'}\._[a-zA-Z]\+\d*_\d

Désobfuscation du pattern 2

Position

Commande

Début de chaine

:%s/\([^+]\){_[a-zA-Z]\+\d*_\d:'\(.\)',_[a-zA-Z]\+_\d:'\d\+'}\._[a-zA-Z]\+\d*_\d/\1'\2/g

Détail de la formule de remplacement \1'\2 :

  • \1 correspond au caractère précédant l’accolade et que nous voulons préserver ([, =, etc…)
  • ' permet d’insérer un guillemet de début de chaine
  • \2 correspond au caractère obfusqué que nous voulons récupérer
     

Position

Commande

Fin de chaine

:%s/+{_[a-zA-Z]\+\d*_\d:'\(.\)',_[a-zA-Z]\+_\d:'\d\+'}\._[a-zA-Z]\+\d*_\d\([,;)\]]\)/\1'\2/g

 

Détail de la formule de remplacement \1'\2 :

  • \1 correspond au caractère obfusqué que nous voulons récupérer
  • ' permet d’insérer un guillemet de fin de chaine
  • \2 correspond au caractère que nous voulons préserver (, ou ; ou ) ou ])

 

Position

Commande

Milieu de chaine

:%s/+{_[a-zA-Z]\+\d*_\d:'\(.\)',_[a-zA-Z]\+_\d:'\d\+'}\._[a-zA-Z]\+\d*_\d/\1/g

3ème pattern : test ternaire et méthode substr()

La troisième technique d’obfuscation consiste à obfusquer les caractères a e et r au sein de tests ternaires suivis d’un appel à la méthode substr() (figure 4).

 

Figure 4 : pattern d’obfuscation basé sur un test ternaire et la méthode substr().

 

Par exemple, le caractère e est obfusqué de la manière suivante :

{key:(((67 > 5) ? true : false) +'').substr(3, 1)}.key

 

Nous retrouvons l’utilisation d’un objet anonyme ({…}) auquel n’est associé, cette fois ci, qu’un seul couple clé / valeur. La valeur associée à la clé se compose d’un test ternaire ((67 > 5) ? true : false) dont le résultat est converti en chaine de caractères (+'') et à laquelle est appliquée la méthode substr().

Un test ternaire se compose de 3 éléments :

Elément

Signification

A gauche de l’opérateur ?

Test à réaliser

A gauche du caractère :

Valeur à assigner si le test est vrai

A droite du caractère :

Valeur à assigner si le test est faux

 

La méthode subsr(start, length) permet d’extraire une partie d’une chaine de caractère. Le paramètre start correspond à l’indice à partir duquel l’extraction commence, et le paramètre length indique combien de caractères extraire.

 

En résumé, pour le caractère e :

  • Le test 67 > 5 est réalisé
  • Le test est vrai, la clé key va donc recevoir la valeur true (en tant que chaine de caractère et non en tant que booléen, grâce à l’opération +'')
  • La méthode substr(3, 1) extrait 1 caractère de la chaine true à partir du caractère ayant l’indice 3 (le compte commence à 0) : e
  • {...}.key permet de récupérer le caractère e

 

L’obfuscation des caractères a et r suit la même logique :

  • Caractère a :
    • Le pattern d’obfuscation du caractère a remplace simplement le booléen true par un test qui est toujours faux (7 > 90)
    • Le test 7899 > 1 est vrai, il renvoie donc le résultat du test 7 > 90, qui renvoie le booléen false, qui est converti en chaine de caractère (+'')
    • Le caractère a est extrait via l’appelle à la méthode substr(1, 1)
  • Caractère r :
    • Le test 78 > 6 renvoie le booléen true, qui est converti en chaine de caractère (+'')
    • Le caractère r est extrait via l’appelle à la méthode substr(1, 1)

Patterns génériques

Caractère

Pattern générique

e

{_[a-zA-Z]\+\d*_\d:(((67 > 5) ? true : false)+'').substr(3,1)}\._[a-zA-Z]\+\d*_\d

a

{_[a-z]\+_\d:(((7899 > 1) ? (7>90) : false)+'').substr(1,1)}\._[a-z]\+_\d

r

{_[a-z]\+\d*_\d:(((78 > 6) ? true : false)+'').substr(1,1)}\._[a-z]\+\d*_\d

Désobfuscation du pattern 3

Le processus de désobfuscation de ces 3 caractères est identique à celui du pattern 2 :

  • début de chaine : préfixe \([^+]\)
  • fin de chaine : préfixe + et suffixe \([,;)\]]\)
  • milieu de chaine : préfixe +

Caractère

Position et commande de désobfuscation

e

Fin de chaine

:%s/+{_[a-zA-Z]\+\d*_\d:(((67 > 5) ? true : false)+'').substr(3,1)}\._[a-zA-Z]\+\d*_\d\([,;)\]]\)/e'\1/g

e

Milieu de chaine

:%s/+{_[a-zA-Z]\+\d*_\d:(((67 > 5) ? true : false)+'').substr(3,1)}\._[a-zA-Z]\+\d*_\d/e/g

a

Début de chaine

:%s/\([^+]\){_[a-z]\+_\d:(((7899 > 1) ? (7>90) : false)+'').substr(1,1)}\._[a-z]\+_\d/\1'a/g

a

Milieu de chaine

:%s/+{_[a-z]\+_\d:(((7899 > 1) ? (7>90) : false)+'').substr(1,1)}\._[a-z]\+_\d/a/g

r

Début de chaine

:%s/\([^+]\){_[a-z]\+\d*_\d:(((78 > 6) ? true : false)+'').substr(1,1)}\._[a-z]\+\d*_\d/\1'r/g

r

Fin de chaine

:%s/+{_[a-z]\+\d*_\d:(((78 > 6) ? true : false)+'').substr(1,1)}\._[a-z]\+\d*_\d\([,;)\]]\)/r'\1/g

r

Milieu de chaine

:%s/+{_[a-z]\+\d*_\d:(((78 > 6) ? true : false)+'').substr(1,1)}\._[a-z]\+\d*_\d/r/g

4ème pattern : mot clé ‘function’ et méthode substr()

Cette technique d’obfuscation consiste à convertir une déclaration de fonction (function (a){return a}) en une chaine de caractères, puis à appeler la méthode substr(0, 1) sur cette chaine (figure 5).

 

Figure 5 : obfuscation du caractère f

 

Ce pattern permet d’obfusquer le caractère f. Dans certains cas l’appel à la méthode substr(0, 1) est précédé d’un appel à la méthode toUpperChar(), permettant d’obfusquer le caractère F.

Patterns génériques

Nous aurons 2 patterns génériques à rechercher :

Caractère

Pattern générique

f

{_[a-zA-Z]\+_\d:(function (a){return a}+'').substr(0,1)}\._[a-zA-Z]\+_\d

F

{_[a-zA-Z]\+_\d:(function (a){return a}+'').toUpperCase().substr(0,1)}\._[a-zA-Z]\+_\d

 

Désobfuscation du pattern 4

Là encore, la désobfuscation se fait en tenant compte des guillemets de début et de fin de chaine.

Caractère

Position et commande de désobfuscation

f

Début de chaine

:%s/\([^+]\){_[a-zA-Z]\+_\d:(function (a){return a}+'').substr(0,1)}\._[a-zA-Z]\+_\d/\1'f/g

f

Fin de chaine

:%s/+{_[a-zA-Z]\+_\d:(function (a){return a}+'').substr(0,1)}\._[a-zA-Z]\+_\d\([,;)\]]\)/f'\1/g

f

Milieu de chaine

:%s/+{_[a-zA-Z]\+_\d:(function (a){return a}+'').substr(0,1)}\._[a-zA-Z]\+_\d/f/g

F

Début de chaine

:%s/\([^+]\){_[a-zA-Z]\+_\d:(function (a){return a}+'').toUpperCase().substr(0,1)}\._[a-zA-Z]\+_\d/\1'F/g

F

Milieu de chaine

:%s/+{_[a-zA-Z]\+_\d:(function (a){return a}+'').toUpperCase().substr(0,1)}\._[a-zA-Z]\+_\d/F/g

 

5ème pattern : méthode String.fromCharCode() et test ternaire

Cette technique d’obfuscation repose sur un test ternaire toujours vrai qui renvoie l’entier 120. Cet entier, qui représente le code ASCII (en base décimal) du caractère obfusqué, est passé en paramètre à la méthode String.fromCharCode() ; il correspond au caractère x (figure 6).

 

Figure 6 : obfuscation du caractère x

 

Le caractère x se trouve toujours en milieu de chaine de caractère, une seule expression sera donc nécessaire :

+{_[a-zA-Z]\+\d*_\d:String.fromCharCode( ((11 > 6) ? 120 : 'h') )}\._[a-zA-Z]\+\d*_\d

Désobfuscation du caractère x :

:%s/+{_[a-zA-Z]\+\d*_\d:String.fromCharCode( ((11 > 6) ? 120 : 'h') )}\._[a-zA-Z]\+\d*_\d/x/g

Fin de la désobfuscation

La majeure partie du script est maintenant désobfusquée. Afin d’en améliorer la lisibilité, quelques ajustements manuels restent à effectuer.

Mise en forme

Le script étant sur une seule ligne, l’ajout de retours à la ligne après les caractères ; et { permet d’en améliorer la lisibilité :

:%s/\([;{]\)/\1\r/g

Correction des concaténations impliquant des caractères spéciaux

Il suffit d’ajouter l’opérateur + et un guillemet de début / fin de chaine lorsque c’est nécessaire. Par exemple :

Math['floor']((Math['random']() * (999)) + 1).exe';

devient :

Math['floor']((Math['random']() * (999)) + 1)+'.exe';
 

Sur le même principe, nous avons la variable char123 qui correspond à la chaine \\ :

  • dans un premier temps nous corrigeons la concaténation. Par exemple :

var wings_Ephesus71=char123ancor.jse';

devient:

var wings_Ephesus71=char123+'ancor.jse';

  • dans un second temps, nous remplaçons le pattern char123 par ladite chaine :

:%s/char123/'\\\\'/g

Fonctionnalités du script malveillant

Le script malveillant est complètement désobfusqué, nous pouvons maintenant analyser ses principales fonctionnalités.

Persistance

Lors de sa première exécution, le script se copie dans le dossier Startup. Il assure ainsi son lancement à chaque démarrage du système d’exploitation (figure 7).

 

Figure 7 : mécanisme de persistance du script malveillant

Mouvements latéraux

Le script énumère les disques réseaux et les disques amovibles connectés à la machine infectée. Pour chaque disque, il dresse la liste des fichiers d’extension *.doc *.xls *.txt *.pdf *.pub *.ppt *.tif *.rtf *.mp3 *.mp4 *.avi et sauvegarde cette dernière dans un fichier temporaire nommé p_o_l_l_o_s.txt. Le script parcours ensuite cette liste de fichiers cibles, et pour chaque entrée il se copie lui-même dans un nouveau fichier nommé nom_du_fichier_cible.jse puis efface le fichier cible original (figure 8). Il s’agit d’un comportement typiquement observé avec les vers informatiques.

 

Thumbnail

Figure 8 : code de propagation du script

 

Le script malveillant usurpe le nom des documents présents sur la machine infectée ; si l’utilisateur ne prête pas attention au changement d’icone lié au changement d’extension, il le propagera en pensant ouvrir son document.

Communication avec le centre de commande

Le script malveillant concatène le chemin vers le répertoire %TEMP% et le chemin vers lui-même dans le répertoire Startup, puis en calcul le hash (figure 9, panneau du haut) ; ce hash, unique pour chaque utilisateur, fait 10 caractères de long. Le script construit ensuite l’url avec laquelle il contactera son centre de commande (figure 9, panneau du bas). Le centre de commande est contacté via l’envoi d’une requête POST contenant le nom du système d’exploitation et la liste des processus en cours d’exécution.

 

Figure 9 : construction de l’url pour contacter le centre de commande

 

L’url se compose de 5 variables :

  • une chaine de 32 caractères ([a-f0-9]) qui pourrait être un identifiant de campagne
  • un nombre aléatoire compris entre 1 et 201
  • un hash utilisateur unique de 10 chiffres
  • un entier pouvant valoir 0, 7 ou le PID d’un processus
  • la longueur de la chaine à partir de laquelle le hash utilisateur a été calculé

Le centre de commande répond en envoyant un binaire qui sera sauvegardé dans le répertoire %TEMP% sous un nom aléatoire, puis exécuté par le script.

Récupération et identification de la charge finale

Avec ces informations, nous pouvons forger une url et récupérer un exemplaire de la charge malveillante à l’aide de wget (figure 10).

 

Figure 10 : récupération de la charge malveillante finale depuis le centre de commande.

 

Lors de son exécution dans notre sandox, le binaire téléchargé a été identifié comme appartenant à la famille Gootkit, un malware bancaire (figure 11). Il a également été possible de récupérer les webinjects, et avec elles la liste des établissements bancaires ciblés : l’exemplaire de Gootkit récupéré ciblait spécifiquement des banques françaises, qui ont été alertées par Orange Cyberdefense.

 

Thumbnail

Figure 11 : exécution de la charge malveillante en sandbox

 

Conclusion

Au cours de cet article, nous avons illustré le processus de désobfuscation du code d’un vers JavaScript et présenté ses principales fonctionnalités : persistance, propagation et téléchargement d’un malware bancaire. La propagation du vers, puisqu’elle se fait via la destruction de données, alerte rapidement qu’un réseau a été compromis. Un malware bancaire, au contraire, vise avant tout la furtivité. Ce tandem est intriguant, et les raisons de cette association restent obscures. D’un coté, nous pouvons imaginer que le centre de commande contacté distribue toute sorte de malwares, dont Gootkit. D’un autre nous pouvons imaginer que les auteurs de l’attaque ont fait le pari que seul le JavaScript serait détecté, laissant Gootkit tapis dans l’ombre, à l’image de la muleta et du capote d’un matador.

IOCs

Malware

Nom de fichier

Sha256

Vers

Ancor.jse

eb60b608bed639d5111adee68addfd5815f1e5c109a0e03a109f808eb77875d0

Gootkit

aléatoire

7ce8f7a379e2f70259efbb901fc758a3c16ef6513abe397fb9035c669bffd03c

Pour aller plus loin

Une approche globale de la sécurité

Ismaël Keddar

Consultant sécurité depuis 2016, j'interviens sur des missions de réponse à incident pour le CSIRT Orange Cyberdefense et participe à des projets de R&D sur l'analyse de malwares. Mes trigger words : rétro-ingénierie, assembleur, malwares