Write UP Private Chall ENI 2 (ESD Rennes_Nantes)

Durant l'année ESD à l'ENI un camarade à créer un challenge histoire de se marrer entre promo (2eme challenge) Enjoy :)

On commence par récupérer le fichier challenge (Il s'agit d'un ZIP) puis par le dézipper, un exécutable sauvage apparaît.

$file chall2.exe 

chall2.exe: PE32 executable (console) Intel 80386, for MS Windows

Lors de l’exécution, il s'agit d'un pendu

===========
||/
||
||
||
||
||
===========

???????????

Enter a letter:

En analysant les appels registres via Procmon je constate qu'un fichier temporaire est dans AppData

Ohhh un script powershell contenant la liste des mots du pendu

...

            if ($pendunb -eq 6) {
write-host "==========="
Write-Host "||/   |"
write-host "||    O"
write-host "||   /|\"
write-host "||   ( )"
write-host "||"
write-host "||"
write-host "==========="    
    }
}

$randomword = get-random -InputObject "forensic","cryptography","steganography","malware","ebios","firewall","python","powershell","artefact","evidence","hexadecimal"
$measureObject = $randomword | Measure-Object -Character
$countletter = $measureObject.Characters
$randomwordarray = $randomword.ToCharArray()

$ask = "?"*$countletter
$letterview = $ask.ToCharArray()

$tentative = 0
$try2win = 0
...

Une fois le pendu gagné le jeu continue ..

OK fini de jouer.

Voici l’histoire...

Il y a quelques temps, l’ENI de Saint-Herblain a accueilli des candidats pour leur faire passer un test d’admission.

C'était pour la formation de Technicien supérieur systèmes et réseaux.

Durant le questionnaire de sélection, les écrans se sont mis à scintiller plusieurs fois.

...

Suite à cet incident, l’ENI m’a demandé de faire une analyse Forensic sur l’ordinateur qu’avait utilisé le candidat

Il n’y avait aucune trace d’utilisation de l’ordinateur. Comme-ci Windows venait d’être installé.

Absolument rien d’anormal à part un fichier. Je n’ai pas pu le copier facilement. Il est assez volatile…

J’ai analysé le fichier et je n’ai rien trouvé de particulier. Tu pourras surement m’aider.

Ce programme a créé une copie exacte de ce fichier et l'a placé quelque part sur ton disque dur.

Met la main dessus et regarde s’il n’y a rien d’anormal.

Pour trouver ce fameux fichier, procmon a été utile

Un fichier docx dans AppData, Analysons ça de près

$unzip Programme_ENI_2019.docx 

Archive:  Programme_ENI_2019.docx
  inflating: docProps/app.xml        
  inflating: docProps/core.xml       
  inflating: word/document.xml       
  inflating: word/endnotes.xml       
  inflating: word/fontTable.xml
  ...

En regardant la taille des médias du docx, une des images est anormalement lourde

$ls -lh word/media 

total 2,4M
-rw-r--r-- 1 root root  19K janv.  1  1980 image1.gif
-rw-r--r-- 1 root root 2,4M févr. 14 14:54 image2.gif

En analysant elle contient 2 zip

$binwalk -e image2.gif 

DECIMAL       HEXADECIMAL     DESCRIPTION
--------------------------------------------------------------------------------
0             0x0             GIF image data, version "89a", 379 x 200
2366159       0x241ACF        Zip archive data, at least v1.0 to extract, compressed size: 26, uncompressed size: 26, name: README.txt
2366263       0x241B37        Zip archive data, at least v2.0 to extract, compressed size: 111432, uncompressed size: 113081, name: devil.jpg
2477826       0x25CF02        End of Zip archive, footer length: 22

$cat README.txt 

NOTHING HERE
YOU MUST DIG

Je salue la performance du troll :)

En essayant de dézipper le zip, il semblerait qu'il soit corrompu

$unzip 241ACF.zip

error:  invalid compressed data to inflate

$unzip -t 241ACF.zip 

Archive:  241ACF.zip
    testing: README.txt              
  error:  invalid compressed data to inflate
At least one error was detected in 241ACF.zip.

Pas de panique Linux est un OS parfait, il est capable de réparer le ZIP ;)

$zip -FF 241ACF.zip --out recovery.zip

Fix archive (-FF) - salvage what can
 Found end record (EOCDR) - says expect single disk archive
Scanning for entries...
 copying: README.txt  (26 bytes)
 copying: devil.jpg  (111432 bytes)
Central Directory found...
EOCDR found ( 1 111667)...

$unzip recovery.zip

Archive:  recovery.zip
  inflating: README.txt              
  error:  invalid compressed data to inflate
  inflating: devil.jpg

L'image devil.jpg n'affiche rien de spécial mais en l'analysant ...

$exiftool devil.jpg

ExifTool Version Number         : 11.16
File Name                       : devil.jpg
Directory                       : .
File Size                       : 110 kB
...
Thumbnail Image                 : (Binary data 14931 bytes, use -b option to extract)

On extrait tout ça pour l'analyser

$exiftool -b devil.jpg >> data.bin

$binwalk data.bin

DECIMAL       HEXADECIMAL     DESCRIPTION
--------------------------------------------------------------------------------
163           0xA3            JPEG image data, JFIF standard 1.01
193           0xC1            TIFF image data, big-endian, offset of first image directory: 8
365           0x16D           JPEG image data, JFIF standard 1.01
395           0x18B           TIFF image data, big-endian, offset of first image directory: 8


$binwalk -D jpeg data.bin

Une miniature pointant vers une URL apparaît en suivant ce lien nous arrivons sur une page reddit affichant du texte brut

Des ténèbres, un bruit retentit ...

"AaAAAaaAAaaAaaAAAaaAAAAaAaaAAaaaAAaAAAAAAAaaaAaAAAaAAAAAAaAAaaAAAaaaAaAaAaaAAAaaAaAaaaaaAaAAAaaAAaaAaAAaAaaAAaAaAaaaAAaAAaAaaaaaAaAAaAAaAaAaAAaaAaAaaaaaAaAAaaAAAaaaAaAaAaaAAAaaAaaAaAAaAaaAAaaAAaaAAaAaAaaaAAaA"

A ce moment là je me suis arraché les cheveux, merci au créateur pour le HINT ;)

L'idée est de convertir chaque caractère en binaire. Avec la différence de valeur, le caractère le plus grand devient 1 et le plus petit devient 0, puis de remplacer chaque caractère par sa nouvelle valeur (Oui le créateur est tordu)

#!/usr/bin/python3

string = str("AaAAAaaAAaaAaaAAAaaAAAAaAaaAAaaaAAaAAAAAAAaaaAaAAAaAAAAAAaAAaaAAAaaaAaAaAaaAAAaaAaAaaaaaAaAAAaaAAaaAaAAaAaaAAaAaAaaaAAaAAaAaaaaaAaAAaAAaAaAaAAaaAaAaaaaaAaAAaaAAAaaaAaAaAaaAAAaaAaaAaAAaAaaAAaaAAaaAAaAaAaaaAAaA")

table = {}

for i in string:
        if i not in table:
                oct = bin(ord(i))[2:]
                table[i] = oct
print(table)
./asciidecode.py 

{'A': '1000001', 'a': '1100001'}

a est plus grand que A donc a = 1 et A = 0

Le script python ci-dessous convertit en binaire , remplace les caractères puis reconverti la chaine binaire en ascii

#!/usr/bin/python3

string = str("AaAAAaaAAaaAaaAAAaaAAAAaAaaAAaaaAAaAAAAAAAaaaAaAAAaAAAAAAaAAaaAAAaaaAaAaAaaAAAaaAaAaaaaaAaAAAaaAAaaAaAAaAaaAAaAaAaaaAAaAAaAaaaaaAaAAaAAaAaAaAAaaAaAaaaaaAaAAaaAAAaaaAaAaAaaAAAaaAaaAaAAaAaaAAaaAAaaAAaAaAaaaAAaA")
table = {}
for letter in string:                           #Pour chaque lettre
        if letter not in table:                 #si la lettre n'est pas dans la chaine
                oct = bin(ord(letter))[2:]      #oct devient sa valeur binaire
                table[letter] = oct             #Correspondance entre la lettre et sa valeur (A : 01000001)
print(table)                                    #Afficher la table de correspondance (Lettre : Valeur binaire)

if table.get("A") > table.get("a"):             #Si la valeur binaire de A en plus grande que a
        A = "1"                                 #A devient 1
        a = "0"                                 #a devient 0
else:                                           #Sinon
        a = "1"                                 #a devient 1
        A = "0"                                 #A devient 0

print("a = ", a)
print("A = ", A)

string = string.replace("A", A)                 #Remplacer A par 1 ou 0 dans la variable string
string = (string.replace("a", a))               #Remplacer a par 1 ou 0 dans la variable string


firstoct = 0
lastoct = 8
flag = []

for octet in string:                            #Pour chaque octet dans la nouvelle string
        octet = string[firstoct:lastoct]        #octet est egal aux 8 premiers caracteres de string
        try:
                bit = chr(int(octet, 2))        #bit contient le resultat de la conversion valeur binaire en ascii
                flag.append(bit)                #Ajout de la valeur bit a la liste flag
        except ValueError:
                pass
        firstoct = firstoct + 8                 #Increment des nombres de octets (+8)
        lastoct = lastoct + 8

flag = "".join(flag)                            #Rassembler chaque caracteres du flag
print(flag)                                     #Affiche le flag

Et en lançant le script ...

./asciidecode.py 

{'a': '1100001', 'A': '1000001'}
a =  1
A =  0
Flag : Luc_Fier_IS_Lucifer

BIM c'est flagué ;)

Remerciement spécial au créateur du challenge Benjamin Perrier, qui a dut se donner du mal à réaliser ce challenge (GG !)

https://fr.linkedin.com/in/benjamin-perrier-952ab0133

Previous Post Next Post