LETTRE DU CERT-WAVESTONE N°11 · ssh -p4443 [email protected] - mdp: e92...
Transcript of LETTRE DU CERT-WAVESTONE N°11 · ssh -p4443 [email protected] - mdp: e92...
Charles IBRAHIM, Senior Consultant
RED TEAM 2.0 : COMMENT AUTOMATISER LA MISE EN PLACE D’UNE INFRASTRUCTURE C&C...............2
Jean MARSAULT, Senior Consultant
WRITEUP DU ROUND DE QUALIFICATION SIGSEGV1........................4
Mahdi BRAIK, Senior Consultant
SOLUTION DU CHALLENGE DE LA GREHACK 2018 (CORRUPTED MEMORIES).......................................................................10
SOMMAIRE
E D I TO
Les années se suivent et se ressemblent. Depuis la création officielle du CERT-Wavestone en
2013, notre équipe n’a cessé de croître et de répondre à de plus en plus d’incidents. L’année
2018 ne déroge pas à la règle jusqu’au point culminant de décembre qui n’a clairement pas été
de tout repos pour notre équipe et nos clients victimes d’attaques (notamment une semaine
à 8 interventions significatives en parallèle…). Quelques mots sur certaines de ces affaires :
/ Compromission d’un SI et dépôt d’une souche inconnue d’un malware : à la suite
de la découverte d’une vulnérabilité sur le SI de la victime, un attaquant s’est
propagé sur l’ensemble des serveurs et a supprimé manuellement les différentes
possibilités de sauvegardes (serveurs de sauvegardes, shadow copies, etc.). Notre
équipe a alors été mandatée pour identifier le vecteur d’intrusion et les moyens de
propagation de l’attaquant. Durant nos investigations nous avons pu mettre la main
sur une souche inconnue du malware que nos reversers continuent à analyser à
l’heure de l’écriture de cet édito. Plus d’informations à venir lors de notre prochaine
lettre ou sur notre blog (https://www.securityinsider-wavestone.com).
/ Vulnérabilité Drupal et compromission de serveurs Web : outre l’étude de
l’exploitation d’une vulnérabilité bien connue sur ce CMS, notre intervention a
surtout consisté en l’analyse du niveau de compromission des systèmes hébergeant
l’application Drupal.
/ Dépôt d’un ransomware et blocage d’un site industriel : après plusieurs semaines
à essayer de traiter l’infection localement, notre client nous a sollicité pour l’aider
à maîtriser la propagation de la menace, puis pour s’assurer des résultats issus de
l’investigation interne.
Bonne année à tous ! Et bon courage pour cette nouvelle année que nous plaçons, côté
CERT-Wavestone, sous les hashtags suivants : #PRIS #PurpleTeam #ICSHoneyNet… plus
d’informations dans nos prochaines lettres !
Vincent NGUYEN, manager, responsable du CERT-WAVESTONE
LETTRE DU CERT-WAVESTONEN°1 1
LA LETTRE DES EXPERTS SÉCURITÉ
2
Motivation du projet
L’outil présenté dans cet article a
été développé pour répondre à des
problématiques propres aux exercices Red
Team :
/ Réduire le temps nécessaire pour
mettre en place l’infrastructure
nécessaire à l’exercice (serveurs de
C&C, infrastructure de phishing, etc.)
/ Faciliter la réalisation des actions les plus fréquentes (cartographie,
génération de code malveillant, etc.)
/ Permettre le lancement des actions les plus complexes en quelques clics
(déploiement de serveurs, utilisation
des services cloud comme AWS)
/ Mettre en place un suivi et une gestion opérationnelle efficace des
opérations à grande échelle
L’objectif principal est de résoudre les
problèmes auxquels les équipes actuelles
sont régulièrement confrontées : multitude
d’outils, manque d’agrégation des résultats,
difficulté à suivre le travail en équipe.
En e f fe t , l e nombre d ’é léments
interconnectés nécessaires à un exercice
Red Team peut rapidement devenir très
grand et leur suivi d’autant plus complexe.
Il devient alors indispensable de centraliser
les données et d’automatiser les actions
qui peuvent l’être pour éviter la perte
d’information (oubli d’activation des logs sur
la distribution cloudfront ou le reverse proxy,
typiquement) et les erreurs (génération
maladroite de certificat TLS, par exemple).
RED Team 2.0 : Comment automatiser la mise en place d’une infrastructure C&C Ce nouvel outil a été présenté en avant-
première à la BOTCONF le 07 décembre
2018. La vidéo de la présentation sera
disponible prochainement.
L’exercice Red Team
Une opération Red Team consiste à tester un
système d’information dans des conditions
réelles. Le but est d’atteindre des objectifs
précis (documents sensibles, serveur
critique, etc.) à travers des moyens variés
pouvant inclure :
/ Des intrusions physiques,
permettant souvent de contourner
des protections logiques
/ Des intrusions logiques, à l’instar
d’un test d’intrusion classique mais
dont le volet post-exploitation est
essentiel
/ De l’ingénierie sociale, en
approchant des individus et en les
amenant à divulguer des informations
sur leur contexte de travail
(technologies et éventuellement
versions des produits manipulés)
L’objectif de cet article est de présenter
ABADDON ; outil développé et utilisé par
Wavestone pour mener à bien ses missions
Red Team.
RED TEAM 2 .0 : COMMENT AUTOMATISER LA MISE EN PLACE D’UNE INFRASTRUCTURE C&C
Écran d’accueil de l’outil
Schéma de l’infrastructure nécessaire pour une mission Red Team
WAVESTONE
DISPOSABLE GOPHISH INSTANCES
TARGET NETWORK
INTERMEDIATE NETWORK
Public key SSH / HTTPS
Domain-fronting, Google APIs, TLS, Application
encryption
Public domain name
<>
W public IP
3. EXFILTRATE
2. EXPLOIT
4. AGGREGATE
1. COMPROMISE
C&C REVERSE PROXY
URL based redirect
EC2 instances
S3 bucket
Custom agent
SES SMTP servers
Cloudfront distributions
Route53 domain names
Windows server
Empire
RED TEAMER
3
RED TEAM 2 .0 : COMMENT AUTOMATISER LA MISE EN PLACE D’UNE INFRASTRUCTURE C&C
Fonctionnalités actuelles de notre outil
Développé sur environ 40 jours de travail
en utilisant le framework Django (version 2),
ABADDON permet actuellement d’effectuer
les actions suivantes en quelques clics :
/ Scan réseau et cartographie des
cibles
/ Mise en place d’infrastructures
Gophish à la volée au sein d’instances
amazon EC2
/ Déploiement de distributions
Cloudfront permettant l’utilisation de
techniques de communication furtives
telles que le domain fronting
/ Compilation puis réception de
connexions d’un Remote Access Tool (RAT) personnalisé, en particulier
configuré pour utiliser le domain fronting lors des communications
avec son serveur de Commande et
de Contrôle (C&C)
Conclusion
L’automatisation des tâches garantit à la fois
de gagner un temps considérable, et d’éviter
des écueils de sécurité opérationnels triviaux.
En investissant un temps raisonnable dans le
développement de techniques de gestion
d’opérations red team parfois innovantes
mais souvent répétitives, Wavestone
libère du temps pour que ses auditeurs
se concentrent sur les tâches les plus
spécifiques et à haute valeur ajoutée.
ABADDON sera sujet à d’importants
développements dans un avenir immédiat,
et il est possible qu’il soit en partie publié,
afin que la communauté sécurité puisse
contribuer à la mise au point d’un outil
performant, et qui permette à un nombre
limité d’auditeurs triés sur le volet de
concurrencer les meilleures opérations
menées pour les organisations les plus
complexes.
Charles IBRAHIM, Senior Consultant
Schéma de l’infrastructure nécessaire pour une mission Red Team
Exemple d’utilisation de la fonctionnalité de cartographie
Compilation du RAT
4
Le premier réflexe à adopter dans ce cas
est de s’orienter sur la cartographie de
l’application : scan de ports, scan des
dossiers, etc. Le challenge interdisant
explicitement le bruteforce en ligne, ces
solutions ne sont pas appliquées ici.
En revanche, deux fichiers sont souvent
présents sur les applications web et
permettent de découvrir tout ou partie de
l’arborescence d’un site :
/ sitemap.xml : fichier XML contenant
l’arborescence des différentes
sections
/ robots.txt : fichier txt visant à
interdire le crawling de certaines
sections aux robots
En naviguant sur le second, l’application
indique que le fichier backup.zip existe :
Le fichier backup.zip est bien accessible,
et une fois téléchargé, demande un mot de
passe pour l’extraction :
Il est facile de procéder au bruteforce de ce
mot de passe à l’aide de la liste rockyou.txt (présente par défaut sur Kali Linux) et de
l’outil fcrackzip :
Le mot de passe est donc passw0rd et
permet de récupérer la source du fichier
PHP, ci-contre :
Le script récupère la valeur du paramètre
GET h1 et la concatène à la chaîne Shrewk avant d’en calculer l’empreinte MD5. Cette
empreinte est ensuite comparée à la chaîne
0 à l’aide de l’opérateur ==.
En temps normal, cette condition n’est pas
réalisable, puisque la sortie de la fonction
md5() a pour longueur fixe 32. En revanche,
puisque l’opérateur de comparaison faible
(en opposition à la comparaison forte avec
l’opérateur ===) est utilisé, il est possible d’en abuser. Notamment, toute chaine de
caractère débutant par 0e et se terminant
par une suite de chiffres est faiblement égale
à la chaîne 0.
Writeup du round de qualification SigSegV1Issus de la génération ayant connu le minitel,
le bas-débit et les écrans cathodiques,
l’équipe formant l’association RTFM a grandi
avec une passion pour la technologie et les
sujets qui s’y rattachent.
L’objectif de l’association est de créer
un événement français sur le thème de la
sécurité informatique, qui s’est déroulé le 1er
décembre 2018 à l’école 42. Celui-ci, nommé
«SIGSEGv1» se basait sur trois axes :
/ Niveau technique avancé
/ Accessibilité géographique
/ Événement à taille humaine
Cet événement a mis en avant différents
sujets tels que le Reverse Engineering, des
démonstrations d’attaques physiques ainsi
que de l’hacking hardware et bas-niveau.
L’accès à l ’événement a été rendu
possible sur validation de challenges
de qualification, qui étaient disponibles
sur la période du 28 septembre au 12
octobre 2018. Plusieurs collaborateurs de
Wavestone ont individuellement pris part
à ces qualifications, dont nous présentons
ci-dessous les writeups.
Web-serveur : la simplicité (par ShrewkRoot)
Description : Bienvenue sur le site le plus
simple du monde avec des failles basiques !
Aucun bruteforce n’est nécessaire. Merci de
ne pas utiliser Dirbuster et outils équivalents
sous peine d’être bannis sur le challenge.
Le site se présente sous la forme d’une page
blanche contenant une vidéo du rappeur
Orelsan :
WRITEUP DU ROUND DE QUALIF ICATION S IGSEGV1
5
WRITEUP DU ROUND DE QUALIF ICATION S IGSEGV1
Les statistiques sont de notre côté, il n’est
pas si improbable d’obtenir une telle chaîne
en calculant l’empreinte d’une chaîne
aléatoire :
La première chaîne de caractère validant la
condition est trouvée en une vingtaine de
minutes, et permet de valider le challenge :
App-script : Fun avec Python (par laxa)
Description : J’ai commencé à développer
des modules pour python, c’est marrant. Je
suis presque sûr que tout est sécurisé jusqu’à
présent.
ssh -p4443 [email protected] - mdp: e92b1b12c450afd60faa9f43cff5412e
La première étape est par conséquent de
se connecter en SSH sur ce serveur pour
découvrir l’environnement :
Dans cette configuration, le fichier flag ne
peut être lu que par un membre du groupe
chall-pwned. Un programme wrapper possède le bit SGID et s’exécutera sous
l’identité du groupe chall-pwned. Enfin, le
fichier Python suivant est fourni :
Après vérification, le package colors n’existe
pas sur PyPI, ce doit être un développement
de l’auteur. Pour aller observer le fichier
source, il suffit d’exécuter les commandes
suivantes :
La source du module Python est située dans
le fichier /usr/local/lib/python2.7/dist-packages/colors/colors.py :
6
Web-client : Javascript Obfusqué (par Synacktiv)
Description : Le javascript est populaire de
nos jours, serez-vous capable de retrouver
le flag ?
Le challenge se présente sous la forme d’un
fichier HTML qui contient un formulaire pour
vérifier le flag :
Il est en général possible de rencontrer deux
types d’obfuscation JavaScript :
Plutôt déroutant à première vue,
puisque aucune argument n’est fourni au
programme... La vulnérabilité vient peut-être
alors du chargement du module. Pour cela,
la documentation de Python décrit très bien
l’ordre de chargement des modules.
Par défaut, les modules sont chargés depuis
les dossiers présents dans la variable sys.path, qui fonctionne de manière similaire à
la variable d’environnement $PATH. Cette
variable est initialisée comme suit :
/ Avec le nom du dossier contenant
le script Python exécuter (les liens
symboliques sont résolus)
/ Avec la variable d’environnement
$PYTHONPATH
/ Avec le dossier d’installation par
défaut des scripts
N’ayant ni les droits d’écriture dans le dossier
courant ou dans le dossier par défaut, la
seconde solution semble la plus adaptée.
L’utilisation d’un binaire SUID ne supprime
pas les variables d’environnement (à l’inverse
du fonctionnement par défaut de sudo).
Pour exploiter la vulnérabilité, le fichier
/tmp/colors.py est créé :
Il est alors possible de récupérer le flag
comme suit :
/ La première construit un code qui
sera désobfusqué et exécuté grâce à
la fonction eval()
/ La seconde construit un code qui
sera désobfusqué et exécuté en
l’ajoutant dynamiquement dans le
code de la page, par exemple via
document.write()
Ce challenge utilise la seconde méthode,
et le code final peut donc être récupéré en
utilisant l’inspecteur HTML de Chrome /
Firefox / Opera :
WRITEUP DU ROUND DE QUALIF ICATION S IGSEGV1
7
Le code complet de la fonction JavaScript
est le suivant :
Les première analyses du code indiquent
que :
/ La fonction Kod consiste à réaliser
une opération XOR entre une chaîne
et une clé, cette dernière étant
répétée si plus courte que la chaîne
à chiffrer
/ La fonction f est appelée sur
validation du formulaire et :
• réalise une vérification sur la clé entrée
dans le formulaire (variable hash)
• déchiffre la variable Secret à l’aide de
la clé pour l’afficher sur la page
Il s’agit donc ici d’un problème de
cryptographie, et la première étape consiste
à trouver la longueur de la clé. Bien que des
analyses statistiques soient possibles, une
méthode plus facile consiste à utiliser le
calcul de la variable hash pour évaluer cette
longueur.
Cette var iable est la somme des
(n-j+33)^31025, n étant le code ASCII du
caractère et j sa position. Ces éléments
sont globalement bornés autour dans
l’intervalle 30000-32000. Il est donc facile
d’approximer la longueur de la clé via
Napprox = 529387 / 31000 = 17.077, soit 17.
Connaissant cette longueur, la variable
Secret peut être présentée sous la forme
suivante, qui aligne les octets du texte chiffré
qui seront déchiffrés à l’aide des mêmes
octets de la clé :
Pour traduire peu à peu le texte, il est possible
d’utiliser la technique du mot probable, qui
fonctionne comme suit : on suppose qu’un
certain mot est présent (non coupé) dans
l’un des blocs. Il est alors possible d’en
déduire une portion de clé probable, et de
déchiffrer les autres portions de blocs avec
cette clé.
Le script suivant permet de faciliter cette
recherche, et d’aboutir peu à peu à la clé
finale, sigsegv{jsIsE4zy} :
WRITEUP DU ROUND DE QUALIF ICATION S IGSEGV1
8
Reverse : antistrings (x0rz)
Description : Faites-moi confiance, XOR n’est
pas la solution.
Le challenge se présente sous la forme
d’un binaire ELF 64-bit strippé. Ce writeup
utilisera Cutter, l’interface graphique de
Radare2. Les premières étapes sont assez
simples, puisque la fonction main ne possède
qu’un appel à une autre fonction :
Si l’on tente d’afficher le graphe de la
fonction située à 0x004009e0, l’erreur
suivante se produit :
Il s’agit là d’une technique anti-reverse,
que l’on peut observer plus en détails dans
l’affichage linéaire de Cutter :
Ci-dessous le détail des instructions :
/ push rax : sauvegarde la valeur
courante de RAX sur la pile
Cryptographie : Un nouveau dialecte (ShrewkRoot)
Descript ion : Nous avons trouvé
un nouveau dia lecte, analysez- le
pour retrouver ce qu’ i l s ignif ie : ȃǹǷȃǵǷȆȋǜǑǣǤǕǗǑǓǕǣǤǠǑǣǣǙǖǑǓǙǜǕȍ
Avant de se lancer à l’emporte-pièce, il
est important de noter qu’il s’agit ici de
caractères multi-bytes. Une méthode simple
pour traduire ces derniers consiste à utiliser
hexdump :
On constate alors rapidement que les
caractères s’écrivent sur deux octets, et
qu’ils se présentent tous sous les formes c7 xx ou c8 yy. Par ailleurs, en supposant que
le texte décodé commence par sigsegv{, on
remarque que :
/ La 1ère lettre (s) et la 4ème lettre (s) sont
codées de manière identique (c8 83)
: il s’agit donc probablement d’une
substitution monoalphabétique ;
/ La 5ème lettre (e) et la 7ème lettre (g)
ont respectivement pour valeur
codée c7 b5 et c7 b7 : le décalage
entre deux lettres est constant, il
s’agit probablement d’une variante
du chiffre de César.
Par conséquent, connaissant le clair et le
chiffré pour une lettre de chaque encodage
(c7 xx et c8 yy), il est facile de coder un
programme qui réalisera la traduction pour
nous :
L’exécution fournit le flag suivant :
sigsegv{LASTEGACESTPASSIFACILE}.
WRITEUP DU ROUND DE QUALIF ICATION S IGSEGV1
9
/ xor eax, eax : remet la valeur de EAX
à 0
/ test eax, eax : teste si la valeur de
EAX est nulle et fixe le flag Z à 1
/ pop rax : récupère la valeur
sauvegardée de RAX depuis la pile
/ jne 0x4009ee : saute à l’adresse
indiquée si le flag Z vaut 0 (non pris)
/ je 0x4009ef : saute à l’adresse
indiquée si le flag Z vaut 1 (pris)
Seulement, les instructions à l’adresse
0x4009ef ne sont pas désassemblées
puisqu’une instruction jmp commence à
l’octet précédent. Le saut à l’octet précédent
n’étant jamais emprunté, il est possible
d’ignorer cette instruction et de demander
le désassemblage à partir de 0x4009ef.
Pour cela, un clic-droit à l’adresse 0x4009ee
fait apparaître le menu suivant :
Il est alors possible d’observer le code qui
devrait être normalement exécuté :
En analysant plus précisément le binaire,
on se rend compte que ces techniques
empêchent simplement le graphe de flot
de contrôle (CFG) et que le désassemblage
reste intact.
L’analyse était donc simplement possible en
ignorant ces bouts de code invalides. Il est
alors facile d’identifier la fonction qui gère
le flag, sub.BB_7c2. Bien que des astuces
anti-reverse soient également présentes, les
lettres du flag sont clairement visibles :
L e f l a g r é c u p é r é e s t a l o r s
sigsegv{W3llPl4y3d}.
Jean MARSAULT, Senior Consultant
WRITEUP DU ROUND DE QUALIF ICATION S IGSEGV1
10
La lecture de la carte s’effectue ainsi par
colonne de la gauche vers la droite ; le
nombre de trous présents sur une même
colonne ainsi que leur emplacement
(ligne-s perforée-s) permettent d’identifier
le caractère stocké.
Bien que certains outils permettent
d’automatiser la lecture de ce type de carte
perforée, un décodage manuel permet
d’arriver rapidement à la solution :
Étape 2 : “More complicated than it should have been”
Pour cette épreuve, un lien vers un site web
ainsi que son code source sont fournis ; le
site permet aux utilisateurs abonnés de créer
et d’animer une timeline :
Une fois enregistré et authentifié, l’interface
web permet d’ajouter des éléments à la
timeline de l’utilisateur et de consulter les
éléments ajoutés :
Solution du challenge de la GreHack 2018 (Corrupted Memories)Comme chaque année, les organisateurs
de la conférence de sécurité GreHack ont
proposé une série de challenges permettant
aux trois challengers les plus rapides de
remporter leur entrée à la conférence.
Cette année, le challenge était constitué de
9 étapes débloquées de façon séquentielle
et intégrant différents sujets liés à la sécurité
informatique (rétro-ingénierie, réseau,
cryptographie, web…).
Étape 1 : “Punched”
Pour cette première épreuve, l’image
suivante est fournie à l’utilisateur :
Afin d’aiguiller un peu plus l’utilisateur, une
indication concernant le format du flag est
aussi transmise ; ce dernier doit respecter
l’expression rationnelle suivante :
La mention « IBM 5081 » présente en bas de
l’image permet d’orienter les recherches et
d’identifier rapidement la fiche Wikipédia détaillant le principe de fonctionnement
des cartes perforées et notamment celles
utilisées par IBM.
On y apprend que ces cartes peuvent
contenir des données textuelles encodées
de la manière suivante :
SOLUTION DU CHALLENGE DE LA GREHACK 2018
Ecran d’accueil du site web du challenge
Formulaire de saisie présent sur l’interface
11
SOLUTION DU CHALLENGE DE LA GREHACK 2018
L’analyse des requêtes transmises (post
authentification) permet d’identifier
rapidement l’utilisation d’un jeton JWT
(dont un rappel du fonctionnement et des
vulnérabilités courantes sont rappelés ici)
assurant le maintien de la session :
L’utilisation du site https://jwt.io/ permet
d’analyser rapidement le contenu du jeton :
Le jeton contient notamment un champs
booléen « admin » initialement faux ; à
ce stade, on peut se douter que l’objectif
du challenge est de réussir à accéder au
contenu de l’administrateur. Or, la fonction
permettant de récupérer l’identité de
l’utilisateur courant est la suivante :
La présence du commentaire, est un indice
permettant de guider le challengeur vers
la solution ; la lecture du code source du
module PyJWT permet d’identifier le
constructeur de la méthode « decode » :
Ainsi, dans le cas d’une exception de type
« InvalidKeyError », la méthode « decode »
est ainsi appelée avec les valeurs des
paramètres suivants :
Cette erreur est notamment levée lors de
l’utilisation de l’algorithme « none » pour la
vérification d’authenticité du jeton :
Par conséquent, il suffit d’envoyer un jeton
avec le contenu suivant afin de valider le
challenge :
La requête suivante permet ainsi d’accéder
et de récupérer le flag :
À la suite de l’envoi de la requête ci-dessus,
le flag est renvoyé par le serveur :
Formulaire de saisie présent sur l’interface
12
Étape 3 : ”Weather station v0.1”
Pour ce troisième niveau, un binaire pour
Arduino (AVR) est fourni au challengeur :
Le chargement de l’exécutable dans IDA
permet d’identifier rapidement certaines
chaines de caractères intéressantes :
La navigation dans le code assembleur
permet ensuite d’identifier la fonction en
charge de la validation de l’entrée utilisateur
à l’adresse 0x49c :
L’analyse de cette fonction ne pose aucune
difficulté ; les caractères du flag sont testés
un par un, en cas d’erreur le message «
Wrong password » est affiché. À la suite de
la validation de l’ensemble des caractères,
le message « Logged in » est affiché.
Finalement, le flag est le suivant :
Étape 4 : “Network”
Pour ce quatrième challenge, une capture
réseau (fichier .cap) est fournie au
challengeur ; l’analyse rapide de celle-ci
permet d’identifier l’unique présence de
flux HTTPS :
La présence de nombreux flux HTTPS laisse
penser à une attaque par facteurs communs
sur les clés publiques RSA. Pour vérifier cette
supposition, le script suivant est exécuté afin
d’extraire l’ensemble des certificats SSL
présentés par les serveurs :
Pour rappel, le chiffrement RSA est effectué
de la manière suivante :
Le déchiffrement s’effectue ainsi de la
manière suivante :
La robustesse de cet algorithme repose sur
le problème de factorisation des grands
nombres en nombres premiers (la clé
publique est constituée uniquement du
couple (N, e)). Cependant, si l’on a deux clés
publiques ((N1, e) et (N2, e)) telles que :
SOLUTION DU CHALLENGE DE LA GREHACK 2018
Extrait du graphe de flot de contrôle de la fonction de validation du mot de passe
Extrait de la liste des communications réseau
13
SOLUTION DU CHALLENGE DE LA GREHACK 2018
Alors, il est relativement aisé de factoriser N1
et N2 en calculant :
Le script suivant est utilisé afin de vérifier la
présence de facteurs communs sur les clés
publiques, et, dans le cas positif, de calculer
la clé privée associée :
Après récupération de certaines clés
privées RSA, il est possible de déchiffrer les
communications associées via Wireshark
afin de récupérer le flag :
Étape 5 : « Find the password »
Pour ce cinquième challenge, un exécutable
linux est fourni :
Le graph de la fonction principale du binaire
est le suivant :
La fonction de « decode_str » effectue
l’opération suivante :
Cette fonction est appelée sur la chaine de
caractère « %7%FbtzGmbhGpsV%k1qwFfxG
Xs4wB89WmW2upfmF5jlEtL4f8gOT4zF[Q
gPliYN7 », la version décodée est la suivante :
L’analyse du reste du code de l’exécutable
(ou la simple reconnaissance du format)
permet ensuite d’identifier cette chaine
comme étant le condensat cryptographique
sha512 tel que formaté par l’utilitaire crypt,
il est ainsi relativement aisé de récupérer
le flag via l’utilisation de l’outil John The
Ripper :
14
Étape 6 : “Micro-probing attack »
Ce sixième challenge est constitué d’un
service accessible via les paramètres
suivants :
Par ailleurs, le code d’un « secure and » est
transmis sous la forme d’un fichier Python
ainsi qu’un fichier README présentant
le fonctionnement du « secure_and ». La
lecture du code source permet d’établir les
relations suivantes :
Si l’on considère que l’on connait b0 et qu’il
vaut 1, on a alors on a les relations suivantes :
Ainsi, connaissant le triplet (b0, c0,3, a4),
nous savons déterminer la valeur du bit
du flag dans le cas b0=1. En automatisant
le processus (par un script python par
exemple), il est aisé de déterminer le flag :
Étape 7 : “Be ready!”
Pour cette étape un exécutable Linux /
RISC-V est fourni :
Une fois de plus, il s’agit d’un challenge de
reverse relativement simple ; la fonction
“main” est constituée des quelques
instructions suivantes :
Ainsi cette fonction appelle cinq sous-
fonctions de manière consécutive ; la
dernière est chargée d’afficher le flag à
l’utilisateur. Ainsi, deux solutions s’offrent
à nous :
/ Analyser statiquement le binaire
(méthode détaillée ci-dessous) ;
/ Exécuter le binaire;
/ Fonction « setFlag » :
SOLUTION DU CHALLENGE DE LA GREHACK 2018
Assembleur de la fonction principale du binaire
15
SOLUTION DU CHALLENGE DE LA GREHACK 2018
/ Fonction « setX_OrTable » :
/ Fonction « applyModify » :
/ Fonction « X_Or » :
Finalement, la mise bout à bout de l’ensemble
des fonctions permet de récupérer le flag :
Étape 8 : “The band”
Pour cette avant-dernière étape, un ELF
compilé pour x86-64 est fourni :
Cette étape a été pour moi la plus
intéressante à résoudre mais aussi la plus
complexe de cette suite de challenges.
Dans la suite de cet article, je propose une
approche visant à analyser entièrement
l’exécutable. Il était évidemment possible
d’accélérer la résolution de ce challenge sans
effectuer cette analyse mais cette approche
semble plus intéressante pour un write-up.
16
Désoffuscation de l’exécutable
Lors de l’ouverture de l’exécutable dans IDA,
on remarque que le binaire a été offusqué
afin de complexifier son analyse. Ainsi, avant
de démarrer l’analyse, il convient d’analyser
la méthode d’offuscation en vue de simplifier
l’analyse. Le pattern d’offuscation est le
suivant :
Les instructions « push rbx » et « pop
rbx » sont utilisées respectivement pour
sauvegarder / restaurer le « contexte »
(en l’occurrence uniquement le registre
rbx). Les instructions « mov rbx, imm »
et « sub rbx, imm » sont utilisées afin de
modifier les EFLAGS et ainsi influencer le
saut conditionnel suivant. Il s’avère en fait
que ce saut est toujours pris (le résultat des
opérations précédentes n’est jamais égal
à 0) et que l’auteur du challenge a utilisé
ces prédicats opaques afin de perturber le
désassemblage de l’exécutable. La rédaction
d’un rapide script IDAPython remplaçant
cette suite d’instruction par des NOP
permet d’obtenir un exécutable plus simple
à analyser.
Analyse de l’exécutable
Suite au nettoyage de l’exécutable, il est
possible de commencer son analyse. La
fonction « main » est relativement rapide à
comprendre, les éléments d’une structure
contenant des positions sont initialisés puis
la fonction cœur de l’exécutable est appelée
avec cette structure en paramètre :
La fonction cœur (nommée ici « core_
function ») est en charge de la validation du
flag rentré par l’utilisateur, son code peut-
être réécrit de la manière suivante :
SOLUTION DU CHALLENGE DE LA GREHACK 2018
Pattern d’offuscation utilisé dans le binaire « theband »
17
La majorité des sous-fonctions appelées
sont aisément analysées, à l’exception des
fonctions « get_user_program » et « start_
robot » qui sont, quant à elles plus complexes.
L’analyse de ces fonctions permet cependant
d’identifier de nombreuses similitudes ;
en effet, l’une comme l’autre se chargent
d’initialiser un ensemble d’éléments avant
de lancer l’exécution d’une autre fonction
(adresse 0x24DA). A la suite du retour de la
fonction appelée (offset 0x24DA), certaines
données du contexte sont récupérées puis
renvoyées à la fonction parente. Une analyse
plus poussée permet de constater que la
fonction commençant à l’adresse 0x24DA
est en fait chargée de lancer l’exécution
d’une sorte de machine virtuelle détaillée
dans la section suivante. Le contexte initialisé
correspond notamment au programme de la
VM ainsi qu’à certaines données spécifiques
à ce programme.
Remarque : de nombreuses fonctions
permettant notamment la gestion de la
mémoire partagée ont été implémentées
par l’auteur du challenge, elles ne seront pas
détaillées dans ce write-up.
Fonctionnement de la « machine virtuelle »
La fonction commençant à l’adresse 0x24DA
est l’une des plus importantes de l’exécutable
puisqu’elle est en charge de l’exécution
de la machine virtuelle implémentée par
l’exécutable.
Note : Le lecteur remarquera que cette
« machine virtuelle » est largement différente
de celles habituellement implémentées dans
les CTF.
Initialisation de la machine virtuelle
L’initialisation de la VM s’effectue via la
création de trois threads par le thread
principal de l’exécutable :
/ 2 threads d’exécution : il s’agit des
threads en charge de l’exécution des
instructions de la machine virtuelle ;
/ 1 thread de décodage : il s’agit du
thread en charge du décodage des
instructions et de leur envoi vers les
threads d’exécution ;
/ 1 thread de fetch : le thread principal
permet de déplacer le curseur
d’instruction courante et de préparer
le CPU pour le prochain cycle.
Décodage des instructions
Le décodage des instructions est effectué
via la fonction implémentée à l’adresse
0x5DD9, cette fonction prend en entrée une
adresse et produit en sortie un message dont
la structure est la suivante :
Le décodage est effectué en fonction
des 9 bits suivants l’adresse transmise en
paramètre.
Transmission des messages et exécution
Les messages produits par la fonction de
décodage des instructions sont transmis
entre les threads à l’aide de pipes. Le champs
« signum » correspond à un numéro de
signal. En effet, des handlers de signaux
sont mis en place pour chaque instruction
du CPU :
Ainsi, lors de la réception du message,
le thread d’exécution appelle la fonction
« kill » avec son propre PID en paramètre
ainsi que le numéro du signal contenu dans
le message afin de provoquer l’exécution de
l’instruction « virtuelle ».
L’indice « track » (ici 10 ou 11), quant à
lui, correspond à un offset utilisé pour le
décodage complet de l’instruction (mode
d’opération, numéro de registre…).
Programmes exécutés par la machine virtuelle
Suite à la compréhension de ces éléments,
il est possible d’écrire un désassembleur
permettant d’obtenir une vision complète du
fonctionnement des programmes exécutés ;
ces programmes sont stockés dans le binaire
aux offsets suivants :
/ R1 (0x2E048) : premier programme
exécuté, il permet de contrôler
l’entrée utilisateur ;
/ R2 (0x2EE98) : second programme
exécuté, il permet d’exécuter le
programme rentré par l’utilisateur ;
/ R3 (0x2F130) : ce programme n’est
jamais exécuté et contient un flag
caché.
SOLUTION DU CHALLENGE DE LA GREHACK 2018
Handlers enregistrés pour la gestion des signaux transmis et correspondants aux différentes instructions du CPU
18
SOLUTION DU CHALLENGE DE LA GREHACK 2018
Programme 1 : la validation de l’entrée utilisateur
Ce programme est simplement utilisé afin
de valider l’entrée de l’utilisateu. Son analyse
permet d’identifier qu’il est possible d’utiliser
les instructions suivantes, séparées par des
points virgules :
Ce programme est aussi en charge de
compter le nombre d’instructions contenues
par le programme de l’utilisateur ; c’est cette
valeur qui est renvoyée à la fonction « core_
function » et vérifiée par la comparaison :
Programme 2 : l’exécution du programme de l’utilisateur
Ce deuxième programme est utilisé afin
d’exécuter le « programme » rentré par
l’utilisateur, pour cela les valeurs des
positions initiales sont conservées dans des
cases mémoires allouées à cet effet et les
opérations suivantes sont effectuées :
/ Right : lorsque cette instruction
est exécutée, la valeur de la case
mémoire associée à la position du
robot est incrémentée ;
/ Left : lorsque cette instruction
est exécutée, la valeur de la case
mémoire associée à la position du
robot est décrémentée ;
/ Goto <label> : lorsque cette
instruction est exécutée, le pointer
d’instructions est incrémenté de
la valeur « label » (pouvant être
négative) ;
/ Skipnext : lorsque cette instruction
est exécutée, le programme vérifie
si la position du robot correspond à
l’une des positions initiales des robots
(emplacement des parachutes). Si
c’est le cas, l’instruction suivante est
ignorée sinon elle est exécutée.
En plus, à chaque cycle d’exécution un
compteur d’instruction est incrémenté
et ce dernier est comparé au nombre
d’instructions maximum pouvant être
exécutées ; lorsque ce nombre est dépassé,
l’exécution du programme est arrêtée.
Finalement, le programme renvoie la position
finale du robot.
Programme 3 : le programme « caché »
Ce dernier programme n’est en fait jamais
exécuté dans le fonctionnement normal
du programme, son fonctionnement est le
suivant :
/ Une entrée utilisateur est
demandée via le message suivant :
/ Le message entré par l’utilisateur est
ensuite comparé au flag caché suivant :
/ Deux messages sont alors
prévus en fonction de la validité
ou non de l’entrée utilisateur :
Cependant, de la manière dont sont
effectuées les comparaisons, seul le
message de « win » peut-être affiché. En
effet, l’instruction équivalente à un « jump if
lower » vérifie la valeur du registre r11 alors
que les comparaisons sont effectuées dans
r3 dans cette fonction.
Résolution du challenge
Avant de débuter la partie suivante,
récapitulons l’ensemble des éléments
que nous possédons actuellement afin de
résoudre le challenge :
Une solution (facilement identifiable en
procédant à tâtons ou via la résolution
d’un système d’équations) du problème
précédent peut être donnée par le
programme suivant qui est un flag valide :
19
SOLUTION DU CHALLENGE DE LA GREHACK 2018
Étape 9 : “43 years before”
Pour ce dernier challenge, un fichier textuel
contenant des instructions d’assembleur
pour microprocesseurs 6502 est fourni.
Après un passage sur le code, il est possible
de recoder le programme en C afin d’obtenir
une meilleure vision des actions réalisées (le
contenu des fonctions n’est pas détaillé dans
ce write-up) :
La compilation puis l’exécution du code
donne le flag suivant :
Cependant, une erreur est renvoyée par le
serveur lorsque je tente de valider l’épreuve…
Après quelques vérifications sur mon code,
je décide de revoir l’intitulé du challenge :
N’ayant volontairement pas util isé
d’émulateur afin de ne pas exécuter un code
avec des potentielles erreurs, je commence
à me dire que l’erreur vient peut-être de
bogues sur le microcontrôleur et non dans
l’implémentation des émulateurs. Quelques
recherches sur Google permettent d’arriver
sur cette page détaillant notamment l’erreur
suivante :
Celle-ci est intrigante car le code fourni
possède de nombreuses instructions du
type (JMP (xx) dont le programmeur aurait
pu se passer) :
En vérifiant les adresses contenues de la
table, il apparait nettement que l’une des
adresses est effectivement de la forme
« xxff » :
A i n s i , l o r s q u e l ’ i n s t r u c t i o n
« JMP(fcttbl+2*4) » est exécutée, à la
place de sauter vers la fonction « fct1 », le
programme effectue un saut à l’adresse
0x00 (c’est-à-dire l’adresse constituée de la
manière suivante : db[0x08ff]db[0x0800]
= 0x0000). Ainsi, plutôt d’exécuter le code
de la fonction « fct1 », un saut est effectué
vers l’adresse 0x0 qui contient l’instruction
« JMP start » (on aurait pu se douter que
cette instruction, a priori inutile, n’avait
pas été placée au hasard) et ensuite le
programme boucle sur l’instruction « JMP
alreadyrunned ».
Finalement, le flag est le suivant :
Ensemble d’instructions de type « JMP (xx) »
Adresse des éléments du tableau « fcttbl »
Mahdi BRAIK, Senior Consultant
2019 I © WAVESTONE
www.wavestone.com
Dans un monde où savoir se transformer est la clé du succès, Wavestone s’est donné pour mission d’éclairer et guider les grandes entreprises et organisations dans leurs
transformations les plus critiques avec l’ambition de les rendre positives pour toutes les parties prenantes. C’est ce que nous appelons « The Positive Way ».