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 !)