Forensic
Introduction
On désigne par informatique légale ou investigation numérique légale l’application de techniques et de protocoles d’investigation numériques respectant les procédures légales et destinée à apporter des preuves numériques à la demande d’une institution de type judiciaire par réquisition, ordonnance ou jugement. On peut donc également la définir comme l’ensemble des connaissances et méthodes qui permettent de collecter, conserver et analyser des preuves issues de supports numériques en vue de les produire dans le cadre d’une action en justice.
Le but de ce chapitre est donc de comprendre l’utilisation de Python pour créer de petits scripts qui vont nous permettre de trouver des preuves informatiques, de retrouver des éléments dispersés dans le disque dur ou sur d’autres médias. Nous découvrirons en plus de celles déjà vues dans les chapitres précédents, d’autres bibliothèques Python telles que Volatility et libPST.
Il existe sur le Web de multiples outils de Forensic tels que Autopsy par exemple, des outils sont regroupés dans les distributions telles que BackTrack ou Bugtraq mais que se passe-t-il quand l’outil que l’on souhaite n’existe pas ?
Les experts en Forensic savent très bien que souvent...
Cryptographie et autres
Souvent, nous allons être confrontés à des fichiers cryptés ; la cible va en effet essayer de cacher l’information.
1. ROT13
Selon Wikipédia, "Le ROT13 (rotate by 13 places) est un cas particulier du chiffre de César, un algorithme simpliste de chiffrement de texte. Comme son nom l’indique, il s’agit d’un décalage de 13 caractères de chaque lettre du texte à chiffrer. Le défaut de ce chiffrement est que s’il s’occupe des lettres, il ne s’occupe pas des symboles et de la ponctuation. C’est pourquoi on doit supprimer toute accentuation du texte à chiffrer. Il ne s’occupe pas non plus des chiffres, ce qui était sans importance puisque les Romains écrivaient leurs chiffres avec des lettres (I, V, X, L, M, etc.). Pour l’utiliser aujourd’hui, il suffit de convertir d’abord les chiffres en utilisant la notation romaine, ou en lettres ("UN" pour1, "DEUX" pour 2...)."
La lettre O devient B, la lettre P devient C...
La librairie string de Python contient une fonction appelée maketrans qui permet de substituer un caractère à un autre.
ROT13=string.maketrans
('abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPRSTUVWXYZ',
'nopqrstuvwxyzabcdefghijklmNOPQRSTUVWXYZABCDEFGHIJKLM')
Dans le script suivant, nous allons ouvrir tous les fichiers .txt et lancer le cryptage ROT13 pour chaque ligne de chaque fichier. Nous allons ensuite regarder si la ligne contient un mot contenu dans le dictionnaire que l’on ouvre au début.
Si c’est le cas, nous afficherons un message indiquant que nous avons trouvé un message encodé en ROT13.
chap8_script1.py
#!/usr/bin/env python
import sys, os, string
ROT13=string.maketrans('abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOP
QRSTUVWXYZ','nopqrstuvwxyzabcdefghijklmNOPQRSTUVWXYZABCDEFGHIJKLM'
)
fichier = open("dictionnaire")
Fichier = fichier.readlines()
for root, dir, files in os.walk(str(sys.argv[1])):
for file in files:
if ".txt" in str(file):
trouvemot = 0
...
Extraction des métadonnées dans les fichiers
Les métadonnées dans les fichiers vont nous permettre de connaître la date de création du fichier, qui l’a créé et avec quel outil.
Nous allons commencer par un script assez amusant qui récupère les métadonnées d’un fichier MP3
1. Métadonnées MP3
La bibliothèque eyeD3 va nous permettre d’examiner les métadonnées des fichiers MP3.
Nous pouvons récupérer grâce à getArtist(), getAlbum(), getTitle() par exemple les données propres au fichier MP3 obtenues par eyeD3.tag().
chap8_script9.py
#!/usr/bin/env python
import eyeD3
tag = eyeD3.Tag()
chemin=raw_input("donnez le chemin du fichier mp3\n")
tag.link(chemin)
print tag.getArtist()
print tag.getAlbum()
print tag.getTitle()
Nous pouvons aussi lire le fichier et accéder à son tag.
if eyeD3.isMp3File(f):
audioFile = eyeD3.Mp3AudioFile(f)
tag = audioFile.getTag()
Nous pouvons aussi récupérer les frames si elles existent.
import eyeD3
tag = eyeD3.Tag()
tag.link("/home/fasm/personnel/chansons/thiefaine/01_113_Cigarette mp3")
for frame in tag.frames:
print frame
Il nous est possible aussi d’ajouter des informations aux tags
tag = eyeD3.Tag()
tag.link('/home/fasm/personnel/chansons/thiefaine/01_113_Cigarette mp3') ...
Fichiers ZIP
1. Lire dans un fichier ZIP
Nous voulons examiner directement un ou plusieurs fichiers contenus dans une archive au format ZIP, sans la décompacter sur le disque.
Une bibliothèque existe, zipfile, qui va nous permettre de travailler directement sur les données contenues dans des fichiers ZIP.
#!/usr/bin/env python
import zipfile
z=zipfile.ZipFile("fichier.zip","r")
for nom in z.namelist() :
print 'le fichier', nom,
nb_octets=z.read(nom)
print 'contient ', len(nb_octets),'octets.'
Nous pouvons aussi consulter le contenu des fichiers.
#!/usr/bin/env python
import zipfile
z = zipfile.ZipFile('test.zip', 'r')
names = z.namelist()
for name in names:
print 'Attente de %s' % name
print z.read(name)
for name in names:
print 'en Attente de %s' % name
f = z.open(name)
contents = f.read()
2. Attaque brute force de mots de passe
Certains fichiers ZIP sont protégés par un mot de passe. Nous pouvons essayer de craquer ces mots de passe en partant d’un dictionnaire, appelé ici passFile et fourni en argument 2 lors du lancement du script, l’argument 1 étant le fichier ZIP.
#!/usr/bin/env python
import...
Lire dans un fichier OpenOffice ou Word
1. Parcourir une arborescence
Nous devons examiner un répertoire ou toute une arborescence de répertoires situés dans un répertoire donné pour itérer sur les fichiers dont les noms correspondent à certains motifs.
Le générateur os.walk, déjà utilisé dans d’autres parties de ce livre, suffit à cette tâche.
#!/usr/bin/env python
import os, fnmatch
def tous_les_fichiers( racine, motifs='*', un_seul_niveau=False,
repertoires = False):
motifs=motifs.split(';')
for chemin, sous_reps, fichiers in os.walk(racine):
if repertoires:
fichiers.extend(sous_reps)
fichiers.sort()
for nom in fichiers:
for motif in motifs:
if fnmatch.fnmatch(nom,motif):
yeld os.path.join(chemin,nom)
break ...
1. Retrouver des e-mails dans des fichiers
Si nous souhaitons récupérer à partir d’une liste de fichiers toutes les adresses e-mail contenues dans ces fichiers, le script suivant pourra nous être très utile.
chap8_script12.py
def grab_email(files = []):
found = []
if files != None:
mailsrch = re.compile(r'[\w\-][\w\-\.]+@[\w\-][\w\-\.]
+[a-zA-Z]{1,4}')
for file in files:
for line in open(file,'r'):
found.extend(mailsrch.findall(line))
u = {}
for item in found:
u[item] = 1
return u.keys()
file=['texte1.txt','texte2.txt','texte3.txt']
retour=grab_email(file)
print retour
Dans le même répertoire, nous allons placer trois fichiers texte, texte1.txt, texte2.txt et texte3.txt ; voici leur contenu :
::::::::::::::
texte1.txt
::::::::::::::
un petit texte tout sympa
qui contient un mail fasm@acissi.net et pis c'est tout
mais regardons le prochain
::::::::::::::
texte2.txt
::::::::::::::
la il n'y a pas de mail mais...
Stéganographie
La stéganographie est une branche particulière de la cryptographie qui consiste non pas à rendre le message inintelligible, mais à le camoufler dans un conteneur de manière à masquer sa présence.
1. Rechercher des informations dans une image
Pour appliquer Python à la stéganographie, nous allons prendre une image, oxygen.png, disponible en téléchargement sur le Net, qui contient des données cachées.
Nous remarquons que cette image comporte une barre avec un dégradé de gris, le message caché doit être ici.
Nous allons utiliser de nouveau la bibliothèque PIL déjà vue et en particulier Image.
#!/usr/bin/env python
import Image
im = Image.open("oxygen.png")
print "Image info:",im.format, im.size, im.mode
#limitation de la zone grise
y_begin = 0
while True:
p = im.getpixel((0, y_begin))
if p[0] == p[1] == p[2]:
break
y_begin += 1
x_end = 0
while True:
p = im.getpixel((x_end, y_begin))
if not p[0] == p[1] == p[2]:
break
x_end += 1
print "Y first coordinate:", y_begin,"nX last coordinate:",x_end
message=[]
for i in range(0,x_end,7):
p = im.getpixel((i, y_begin))
message.append(chr(p[0]))
print ''.join(message),
#First run gives: [105, 110, 116, 101, 103, 114, 105, 116, 121]
message=[105, 110, 116, 101, 103, 114, 105, 116, 121]
print '(',''.join([chr(x) for x in message]),')'
Toutes les librairies, fonctions et méthodes ont déjà été vues précédemment, nous n’y reviendrons donc pas ici.
2. Cacher un message dans une image
Chaque pixel est défini par un triplet de trois nombres entiers compris entre 0 et 255, le premier donnant la composante rouge, le deuxième...
Volatility
L’analyse du contenu de la mémoire volatile (RAM) permet de trouver différentes informations, sur l’état du système par exemple.
L’analyse de la mémoire volatile va permettre de découvrir des connexions réseau ouvertes, les mots de passe utilisés récemment, les fichiers effacés, le contenu du registre Windows...
Volatility est un des plus grands projets Open Source pour le Forensic. C’est un framework Python avec de nombreuses librairies permettant d’extraire des données des mémoires volatiles.
La structure de Volatility permet de développer des modules pour extraire des données spécifiques de la RAM.
Par défaut les modules sont :
-
Affichage de la liste des connexions réseau ouvertes et scan des objets de connexion.
-
Affichage de la liste des DLL chargées par chaque processus.
-
Affichage des fichiers ouverts pour chaque processus.
-
Réalisation de différents dump.
-
Identification de la propriété des images incluant les données, l’horaire, la date et le lieu.
-
Affichage d’une liste des clés de registre pour chaque processus trouvé dans la table des processus.
Des plugins ont été ajoutés par diverses personnes, dont ceux-ci :
-
CryptoScan : trouve les passphrases TrueCrypt.
-
Suspicious : trouve les processus suspects.
-
Keyboardbuffer : extrait le buffer de clavier utilisé par le BIOS.
-
Getsids : trouve les informations de l’utilisateur qui a lancé les processus (SID).
1. Informations sur l’image
Volatility est assez simple d’installation, des exemples d’utilisation sont très bien documentés sur le site. Voici, pour vous donner l’eau à la bouche, un exemple issu du site de Volatility.
Recherche dans le fichier dump des informations sur le système :
2. Processus et DLL
Recherche dans le fichier dump des processus et DLL lancés et utilisés par le système :
3. Capture de mots de passe hachés
Obtenir les mots de passe hachés après la pénétration d’un système Windows est commun pour un attaquant.
Volatility fait cela très facilement. Nous allons d’abord regarder comment utiliser les plug-ins nécessaires à cela et essayer de trouver...
Analyse des points d’accès sans fil dans la base de registre
Le registre Windows contient une base de données hiérarchique contenant la configuration du système où se trouvent les informations relatives aux accès sans fil.
Sous Windows Vista par exemple, nous retrouverons ces informations dans : HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\ NetworkList\Signatures\Unmanaged.
Nous pouvons à partir du shell (cmd.exe) lister tout cela :
C:\Windows\system32>reg query "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\
Windows NT\ CurrentVersion\NetworkList\Signatures\Unmanaged" /s
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows
NT\CurrentVersion\NetworkList\Signatures\
Unmanaged\010103000F0000F0080000000F0000F04BCC2360E4B8F7DC8BDAF
AB8AE4DAD8 62E3960B979A7AD52FA5F70188E103148
ProfileGuid REG_SZ {3B24CE70-AA79-4C9A-B9CC-83F90C2C9C0D}
Description REG_SZ Hooters_San_Pedro
Source REG_DWORD 0x8
DnsSuffix REG_SZ
FirstNetwork REG_SZ Public_Library
DefaultGatewayMac REG_BINARY 00115024687F0000
Le registre stocke l’adresse MAC de la passerelle comme type REG_Binary. Dans l’exemple précédent, nous la retrouvons sous la forme 00115024687F0000, soit \x00\x11\x50\x24\x68\x7F\x00\x00, mais conventionnellement, l’écriture de l’adresse MAC serait 00:11:50:24:68:7F:00:00.
Créons donc une fonction...
Retrouver les éléments supprimés (dans la corbeille)
La corbeille, en fonction des systèmes d’exploitation, peut avoir un nom différent dans l’arborescence.
Nous pouvons créer un petit script qui va tester cela et nous donner le bon chemin. Nous devrons bien sûr renseigner plus amplement la liste définie pour des systèmes dans d’autres langues.
import os
def returnDir():
dirs=['C:\\Recycler\\','C:\\Recycled\\','C:\\$Recycle.Bin\\']
for recycleDir in dirs:
if os.path.isdir(recycleDir):
return recycleDir
return None
Après avoir découvert le chemin de la corbeille Windows, nous devrons inspecter son contenu.
C:\RECYCLER>dir /a
Volume in drive C has no label.
Volume Serial Number is 882A-6E93
Directory of C:\RECYCLER
04/12/2011 09:24 AM <DIR> .
04/12/2011 09:24 AM <DIR> ..
04/12/2011 09:56 AM <DIR> S-1-5-21-1275210071-1715567821-
725345543-1005
04/12/2011 09:20 AM <DIR> S-1-5-21-1275210071-1715567821-
725345543- 500
0...
Mise en pratique
1. Décryptage
Énoncé
Nous avons cette phrase :
nkxtg uwt nc ugewtkvg kphqtocvkswg gv ng gvjkecn jcemkpi : vqwv kphqtocvkekgp ugpukdknkug cw eqpegrv fg nc ugewtkvg kphqtocvkswg ocku- pqxkeg qw fgdwvcpv fcpu ng fqockpg fg nc ugewtkvg fgu uauvgogu f’kphqtocvkqpu. Sqp cfcig guv crrtgpftg ngu cvvcswgu rqwt okgwz ug fghgpftg.
Créez un script qui la décrypte.
Correction
import string
cyphertext = "nkxtg uwt nc ugewtkvg kphqtocvkswg gv ng gvjkecn
jcemkpi : vqwv kphqtocvkekgp ugpukdknkug cw eqpegrv fg nc ugewtkvg
kphqtocvkswg ocku pqxkeg qw fgdwvcpv fcpu ng fqockpg fg nc
ugewtkvg fgu uauvgogu f'kphqtocvkqpu. Sqp cfcig guv crrtgpftg ngu
cvvcswgu rqwt okgwz ug fghgpftg."
fromlist = "abcdefghijklmnopqrstuvwxyz"
tolist = "cdefghijklmnopqrstuvwxyzab"
transtable = string.maketrans(fromlist, tolist)
print string.translate(cyphertext, transtable)
2. OCR
Énoncé
Vous trouverez en téléchargement depuis la page Informations générales un fichier texte nommé ocr.txt.
Un mot y est caché et chacune de ses lettres est très « rare » dans le fichier. Recherchez les lettres qui n’apparaissent qu’une seule fois.
Correction
mess = open("ocr.txt").read()
dict = {}
for ch in mess:
...