Algorithme
Les deux types d'algorithmes
Les deux principaux algorithmes de brute-forcage sont :
- Par liste de mots : on essaie chaque mot d'une liste de mots (wordlist), c'est la plus efficace et la plus facile à mettre en place, mais elle ne vient pas à bout des mots de passe les plus complexes...
- Par génération : on essaie toutes les combinaisons possibles avec un jeu de caractères donne, elle permet de trouver à coup sûr le mot de passe, mais peut durer des siècles ! (littéralement)
Ici nous verrons la méthode par génération, elle est bien plus intéressante en termes de logique de code.
Les bases en mathématiques
En mathématiques les bases sont le nombre de symboles utilisés pour représenter un nombre. Les trois bases les plus utilisées sont :
- Décimale (base 10) : elle utilise les symboles 0, 1, 2, 3, 4, 5, 6, 7, 8 et 9.
- Binaire (base 2) : elle utilise les symboles 0 et 1.
- Hexadécimale (base 16) : elle utilise les symboles 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, A, B, C, D, E, F.
Cela signifie simplement que dès lors que l'on arrive au dernier symbole F (pour l'hexadécimal) on passe au symbole suivant pour le symbole à gauche du F et on remet le premier symbole à la place du F, soit 10.
Les bases appliquées au brute-force
Nous pouvons reprendre le système des bases mais en y ajoutant les symboles que nous souhaitons utilisons pour notre génération. Cette liste de symbole nous donnera notre jeu de caractères
⚠ Attention ⚠ : En mathématiques, le vide à la gauche d'un nombre est équivalent au premier symbole (en base 10 le nombre 53 est égale à 00053), cependant nous devons aussi différencier le premier symbole du symbole vide !
Prenons le jeu de caractères suivants :
0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghikjlmnopqrstuvwxyz[]~@#$-_+{};:,./\?
Cela nous donne la génération suivante :
0 1 2 3 ... / \ ? 00 01 02 03 ... 0/ 0\ 0? 10 11 12 13 etc...
Et voilà comment fonctionne cet algorithme, il ne reste plus qu'à le coder.
L'algorithme en code
Voici comment fonctionne l'algorithme, un tableau (un array) contenant pour chaque case le numéro (l'index) du caractère auquel il correspond (le -1 représentant le vide).
À chaque tour on incrémente la première case, si elle dépasse 80 (le nombre de caractère présent dans le jeu de caractères) on la remet à 0 et on incrémente la case suivante, et si la case suivante a dépassée on réitère jusqu'à arriver à une case contenant un -1.
Ainsi le tableau :
[ 3, 56, 12, -1, -1, -1 ]
Nous donne le mot de passe :
2tB
package main
// Importation des bibliotheques
import (
"crypto/sha256"
"encoding/hex"
"fmt"
"os"
"strings"
)
func main() {
// Definition des variables
hash := "6ca13d52ca70c883e0f0bb101e425a89e8624de51db2d2392593af6a84118090"
salt := "123"
minsize := 0
maxsize := 10
charset := "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghikjlmnopqrstuvwxyz[]~@#$-_+{};:,./\\?"
// Calcul des variables
carray := strings.Split(charset, "")
csize := len(carray)
array := make([]int, 0)
for i := 0; i < maxsize; i++ {
if i < minsize {
array = append(array, 0)
} else {
array = append(array, -1)
}
}
maxrang := maxsize - 1
// Boucle du brute forcage
for {
// Reset et increment
password := ""
array[0] += 1
// Calcul de l'array
for i := 0; i < maxsize; i++ {
// Gestion du calcul de base
if array[i] == csize {
if i < maxrang {
array[i] = 0
array[i+1] += 1
} else {
os.Exit(0) // Fin
}
}
// Conversion en caracteres
if array[i] > -1 {
password += carray[array[i]]
} else {
break
}
}
// Hash le mot de passe genere en sha256
h := sha256.Sum256([]byte(password + salt))
hashed := hex.EncodeToString(h[:])
// Verifi la correspondance
if string(hashed) == hash {
fmt.Print("Le mot de passe est : \"" + password + "\"")
os.Exit(0) // Fin
}
}
}
// Importation des bibliotheques
#include <iostream>
#include <string>
#include "sha256.h"
using namespace std;
int main()
{
// Definition des variables
string hash = "6ca13d52ca70c883e0f0bb101e425a89e8624de51db2d2392593af6a84118090";
string salt = "123";
int minsize = 0;
int maxsize = 10;
string charset = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghikjlmnopqrstuvwxyz[]~@#$-_+{};:,./\\?";
// Calcul des variables
int csize = charset.length() + 1;
char* carray = new char[csize];
strcpy(carray, charset.c_str());
int* array = new int[maxsize];
for (int i = 0; i < maxsize; i++)
{
array[i] = i < minsize ? 0 : -1;
}
int maxrang = maxsize - 1;
// Boucle du brute forcage
while (true)
{
// Reset et increment
string password = "";
array[0]++;
// Calcul de l'array
for (int i = 0; i < maxsize; i++)
{
// Gestion du calcul de base
if (array[i] == csize)
{
if (i < maxrang)
{
array[i] = 0;
array[i + 1]++;
}
else
{
exit(0); // Fin
}
}
// Convertion en caracteres
if (array[i] > -1)
{
password += carray[array[i]];
}
else
{
break;
}
}
// Hash le mot de passe genere en sha256
string hashed = sha256(password + salt);
// Verifi la correspondance
if (hashed == hash)
{
std::cout << "Le mot de passe est : \"" + password + "\"";
exit(0); // Fin
}
}
}
# Importation des bibliotheques
import sys
from hashlib import sha256
# Definition des variables
hash = '6ca13d52ca70c883e0f0bb101e425a89e8624de51db2d2392593af6a84118090'
salt = '123'
minsize = 0
maxsize = 10
charset = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghikjlmnopqrstuvwxyz[]~@#$-_+{};:,./\\?'
# Calcul des variables
rang = range(maxsize)
maxrang = maxsize - 1
carray = list(charset)
csize = len(carray)
array = [0 if _ < minsize else -1 for _ in rang]
# Boucle du brute forcage
while True:
# Reset et increment
password = ''
array[0] += 1
# Calcul de l'array
for i in rang:
# Gestion du calcul de base
if array[i] == csize:
if i < maxrang:
array[i] = 0
array[i + 1] += 1
else:
sys.exit(0) # Fin
# Conversion en caracteres
if array[i] > -1:
password += carray[array[i]]
else:
break
# Hash le mot de passe genere en sha256
hashed = sha256((password + salt).encode('utf-8')).hexdigest()
# Verifi la correspondance
if hashed == hash:
print('Le mot de passe est : "' + password + '"')
sys.exit(0) # Fin
// Importation des bibliotheques
using System;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
namespace CSharp
{
class Program
{
static void Main(string[] args)
{
// Definition des variables
string hash = "6ca13d52ca70c883e0f0bb101e425a89e8624de51db2d2392593af6a84118090";
string salt = "123";
int minsize = 0;
int maxsize = 10;
string charset = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghikjlmnopqrstuvwxyz[]~@#$-_+{};:,./\\?";
// Calcul des variables
char[] carray = charset.ToCharArray();
int csize = carray.Length;
int[] array = new int[maxsize];
for (int i = 0; i < maxsize; i++)
{
array[i] = i < minsize ? 0 : -1;
}
int maxrang = maxsize - 1;
// Boucle du brute forcage
while (true)
{
// Reset et increment
string password = "";
array[0]++;
// Calcul de l'array
for (int i = 0; i < maxsize; i++)
{
// Gestion du calcul de base
if (array[i] == csize)
{
if (i < maxrang)
{
array[i] = 0;
array[i + 1]++;
}
else
{
Environment.Exit(0); // Fin
}
}
// Convertion en caracteres
if (array[i] > -1)
{
password += carray[array[i]];
}
else
{
break;
}
}
// Hash le mot de passe genere en sha256
string hashed = String.Concat(SHA256.Create()
.ComputeHash(Encoding.UTF8.GetBytes(password + salt))
.Select(item => item.ToString("x2")));
// Verifi la correspondance
if (hashed == hash)
{
Console.WriteLine("Le mot de passe est : \"" + password +"\"");
Environment.Exit(0); // Fin
}
}
}
}
}
#AutoIt3Wrapper_UseX64=y
#AutoIt3Wrapper_Change2CUI=y
; Importation des bibliotheques
#include <Crypt.au3>
#include <String.au3>
#include <StringConstants.au3>
; Definition des variables
$hash = '6ca13d52ca70c883e0f0bb101e425a89e8624de51db2d2392593af6a84118090'
$salt = '123'
$minsize = 0
$maxsize = 10
$charset = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghikjlmnopqrstuvwxyz[]~@#$-_+{};:,./\?'
; Calcul des variables
$carray = StringSplit($charset, '', 2)
$csize = UBound($carray)
Dim $array[$maxsize + 1]
For $i = 0 To $maxsize
$array[$i] = $i < $minsize ? 0 : -1
Next
$maxrang = $maxsize - 1
; Boucle du brute forcage
While 1
; Reset et increment
$password = ""
$array[0] += 1
; Calcul de l'array
For $i = 0 To $maxsize
; Gestion du calcul de base
If $array[$i] == $csize Then
If $i < $maxrang Then
$array[$i] = 0
$array[$i + 1] += 1
Else
Exit ; Fin
EndIf
EndIf
; Conversion en caracteres
If $array[$i] > -1 Then
$password &= $carray[$array[$i]]
Else
ExitLoop
EndIf
Next
; Hash le mot de passe genere en sha256
$hashed = StringMid(_Crypt_HashData($password & $salt, $CALG_SHA_256), 3)
; Verifi la correspondance
If $hashed = $hash Then
ConsoleWrite('Le mot de passe est : "' & $password & '"' & @CRLF)
Exit ; Fin
EndIf
WEnd