Skip to main content

Rule Breaker 1

🛡️ Writeup – Rule Breaker 1

  • Catégorie : Hash Cracking

  • Points : 500

  • Points obtenus : 50

  • Auteur : Suvoni

  • CTF : L3akCTF2025

  • Résolu par : Obso11337

  • Ce challenge a été résolu en 182ème position sur 258 solves


📝 Description


🔍 Analyse initiale

  • Il y a trois hashes à cracker.

  • Les mots de passe correspondant aux hashes se trouvent dans le dictionnaire rockyou.txt

  • Le format du flag est : L3AK{pass1_pass2_pass3}

  • Les hashes fournis sont :

    5e09f66ae5c6b2f4038eba26dc8e22d8aeb54f624d1d3ed96551e900dac7cf0d

    fb58c041b0059e8424ff1f8d2771fca9ab0f5dcdd10c48e7a67a9467aa8ebfa8

    4ac53d04443e6786752ac78e2dc86f60a629e4639edacc6a5937146f3eacc30f


⚙️ Outils utilisés


🧪 Étapes de résolution

  • Hash 1 (5e09f66ae5c6b2f4038eba26dc8e22d8aeb54f624d1d3ed96551e900dac7cf0d)

    • Il faut ajouter 3 caractères à la fin dans cet ordre : un caractère spécial, un nombre et une majuscule

      • Test 1 : Ajout d'une règle de transformation à hashcat

        • Script pour générer toutes les règles possibles en respectant les 3 conditions :

          • #!/bin/bash

            symbols='!@#$%^&*'
            digits='0123456789'
            letters='ABCDEFGHIJKLMNOPQRSTUVWXYZ'

            > suffixes.txt

            # Boucles avec protection contre l'expansion des caractères spéciaux
            while IFS= read -r s; do
            while IFS= read -r d; do
              while IFS= read -r l; do
                echo "\$${s}\$${d}\$${l}" >> suffixes.txt
              done <<< "$(echo "$letters" | fold -w1)"
            done <<< "$(echo "$digits" | fold -w1)"
            done <<< "$(echo "$symbols" | fold -w1)"
          • Ce script génère toutes les combinaisons possibles formées de :

            1. Un symbole spécial (parmi !@#$%^&*)

            2. Un chiffre (de 0 à 9)

            3. Une lettre majuscule (de A à Z)

            Et il les écrit dans un fichier nommé suffixes.txt

          • On lance hashcat pour tenter de cracker le hash :

             hashcat -O -w 3 -m 1400 -a 1 hash1.txt -o cracked1.txt /tmp/rockyou.txt suffixes.txt
            Option / Argument Description
            hashcat Lance le programme Hashcat
            -O Active l’optimisation des performances (ignore certaines règles trop complexes)
            -w 3 Définit la charge de travail GPU : niveau 3 (élevé)
            -m 1400 Spécifie le type de hash : 1400 = SHA-256
            -a 1 Définit le mode d’attaque : 1 = attaque combinée (wordlist + wordlist)
            hash1.txt Fichier contenant les hashes à casser
            -o cracked1.txt Fichier de sortie où seront enregistrés les hashes cassés + mots de passe trouvés
            /tmp/rockyou.txt Première wordlist utilisée dans l’attaque
            suffixes.txt Deuxième wordlist pour générer des combinaisons avec la première
          • Voici l'output de hashcat

            hashcat (v6.2.6) starting

            OpenCL API (OpenCL 3.0 PoCL 3.1+debian Linux, None+Asserts, RELOC, SPIR, LLVM 15.0.6, SLEEF, DISTRO, POCL_DEBUG) - Platform #1 [The pocl project]
            ============================================================================================================
            Device #1: pthread-haswell-13th Gen Intel(R) Core(TM) i9-13900KF, 30986/62037 MB (8192 MB allocatable), 32MCU,

            Minimum password length supported by kernel: 0
            Maximum password length supported by kernel: 31

            Dictionary cache hit:
            Filename..: /tmp/rockyou.txt,
            Passwords.: 14344384,
            Bytes.....: 139921497,
            Keyspace..: 14344384,

            Dictionary cache hit:
            Filename..: suffixes.txt,
            Passwords.: 2080,
            Bytes.....: 8320,
            Keyspace..: 2080,

            Hashes: 1 digests; 1 unique digests, 1 unique salts
            Bitmaps: 16 bits, 65536 entries, 0x0000ffff mask, 262144 bytes, 5/13 rotates

            ...

            Session..........: hashcat
            Status...........: Cracked
            Hash.Mode........: 1400 (SHA2-256)
            Hash.Target......: 5e09f66ae5c6b2f4038eba26dc8e22d8aeb54f624d1d3ed9655...c7cf0d
            Time.Started.....: Sat Jul 12 16:57:39 2025 (37 secs)
            Time.Estimated...: Sat Jul 12 16:58:16 2025 (0 secs)
            Kernel.Feature...: Optimized Kernel
            Guess.Base.......: File (/tmp/rockyou.txt), Left Side
            Guess.Mod........: File (suffixes.txt), Right Side
            Speed.#1.........:   420.3 MH/s (54.17ms) @ Accel:1024 Loops:1024 Thr:1 Vec:8
            Recovered........: 1/1 (100.00%) Digests (total), 1/1 (100.00%) Digests (new)
            Progress.........: 15609910944/29836318720 (52.32%)
            Rejected.........: 2905760/15609910944 (0.02%)
            Restore.Point....: 7472490/14344384 (52.09%)
            Restore.Sub.#1...: Salt:0 Amplifier:1024-2048 Iteration:0-1024
            Candidate.Engine.: Device Generator
            Candidates.#1....: iankerry$9K -> hunie28*8T
            Hardware.Mon.#1..: Temp: 93c Util: 88%

            Started: Sat Jul 12 16:57:38 2025
            Stopped: Sat Jul 12 16:58:18 2025

            Le hash a été cracké!

             

          • On vérifie :

            • $ cat cracked1.txt
              5e09f66ae5c6b2f4038eba26dc8e22d8aeb54f624d1d3ed96551e900dac7cf0d:hyepsi^4B
            • echo -n "hyepsi^4B" | sha256sum
              5e09f66ae5c6b2f4038eba26dc8e22d8aeb54f624d1d3ed96551e900dac7cf0d  -

              Premier hash vaildé!

  • Hash 2 (fb58c041b0059e8424ff1f8d2771fca9ab0f5dcdd10c48e7a67a9467aa8ebfa8)

    • Une faute de frappe a été faite lors de la saisie du mot de passe. Il faut considérer une faute de frappe comme la suppression d’un seul caractère du mot de passe.

      • On doit tester chaque mot de rockyou.txt en le raccourcissant d’un caractère, à chaque position possible. Plutôt que de générer un fichier géant, on va utiliser un script Python :

        #!/usr/bin/env python3
        with open("/tmp/rockyou.txt", "r", encoding="latin-1") as f:
           words = f.read().splitlines()

        with open("rockyou_typo.txt", "w", encoding="latin-1") as out:
           for word in words:
               if len(word) > 1:
                   for i in range(len(word)):
                       variant = word[:i] + word[i+1:]
                       out.write(variant + "\n")
      • On lance hashcat pour tenter de cracker le hash :

        hashcat -O -w 3 -m 1400 -a 0 hash2.txt -o cracked2.txt ./rockyou_typo.txt
        Élément Description
        -O Active l’optimisation des performances (peut ignorer certaines règles complexes)
        -w 3 Définit une charge de travail GPU élevée (niveau 3 = rapide, mais intensif)
        -m 1400 Spécifie le type de hash : SHA-256
        -a 0 Mode d’attaque : attaque par dictionnaire simple
        hash2.txt Fichier contenant les hashes à casser
        -o cracked2.txt Fichier de sortie : écrit les hashes cassés avec les mots de passe trouvés
        ./rockyou_typo.txt Wordlist personnalisée contenant des mots avec une faute de frappe (1 caractère supprimé)
      • Voici l'output de hashcat:

        hashcat (v6.2.6) starting

        OpenCL API (OpenCL 3.0 PoCL 3.1+debian Linux, None+Asserts, RELOC, SPIR, LLVM 15.0.6, SLEEF, DISTRO, POCL_DEBUG) - Platform #1 [The pocl project]
        ==================================================================================================================================================
        Device #1: pthread-haswell-13th Gen Intel(R) Core(TM) i9-13900KF, 30986/62037 MB (8192 MB allocatable), 32MCU,

        Minimum password length supported by kernel: 0
        Maximum password length supported by kernel: 31

        Hashes: 1 digests; 1 unique digests, 1 unique salts
        Bitmaps: 16 bits, 65536 entries, 0x0000ffff mask, 262144 bytes, 5/13 rotates
        Rules: 1

        Optimizers applied:
        Optimized-Kernel,
        Zero-Byte,
        Precompute-Init,
        Early-Skip,
        Not-Salted,
        Not-Iterated,
        Single-Hash,
        Single-Salt,
        Raw-Hash,

        Watchdog: Temperature abort trigger set to 90c

        Host memory required for this attack: 8 MB

        Dictionary cache built:
        Filename..: ./rockyou_typo.txt,
        Passwords.: 125574919,
        Bytes.....: 1221106149,
        Keyspace..: 125573586,
        Runtime...: 3 secs,
        [17:10]
        Session..........: hashcat
        Status...........: Cracked
        Hash.Mode........: 1400 (SHA2-256)
        Hash.Target......: fb58c041b0059e8424ff1f8d2771fca9ab0f5dcdd10c48e7a67...8ebfa8
        Time.Started.....: Sat Jul 12 17:10:00 2025 (1 sec)
        Time.Estimated...: Sat Jul 12 17:10:01 2025 (0 secs)
        Kernel.Feature...: Optimized Kernel
        Guess.Base.......: File (./rockyou_typo.txt)
        Guess.Queue......: 1/1 (100.00%)
        Speed.#1.........: 18013.5 kH/s (0.80ms) @ Accel:1024 Loops:1 Thr:1 Vec:8
        Recovered........: 1/1 (100.00%) Digests (total), 1/1 (100.00%) Digests (new)
        Progress.........: 9307522/125573586 (7.41%)
        Rejected.........: 1410/9307522 (0.02%)
        Restore.Point....: 9274754/125573586 (7.39%)
        Restore.Sub.#1...: Salt:0 Amplifier:0-1 Iteration:0-1
        Candidate.Engine.: Device Generator
        Candidates.#1....: thurma34 -> thecdez
        Hardware.Mon.#1..: Temp: 71c Util: 0%

        Started: Sat Jul 12 17:09:57 2025
        Stopped: Sat Jul 12 17:10:02 2025
      • On vérifie :

        • $ cat cracked2.txt
          fb58c041b0059e8424ff1f8d2771fca9ab0f5dcdd10c48e7a67a9467aa8ebfa8:thecowsaysmo
        • echo -n "thecowsaysmo" | sha256sum
          fb58c041b0059e8424ff1f8d2771fca9ab0f5dcdd10c48e7a67a9467aa8ebfa8  -

          Second hash validé!

  • Hash 3 (4ac53d04443e6786752ac78e2dc86f60a629e4639edacc6a5937146f3eacc30f)

    • Il faut modifier encore une fois le dictionnaire en leetifiant les voyelles

      • Script pour préparer le dictionnaire :

        #!/usr/bin/env python3 
        from itertools import product

        # Mapping des substitutions possibles,
        leet_map = {
           'a': ['4'],
           'e': ['3'],
           'i': ['1'],
           'o': ['0']
        }

        def leetify_strict(word):
           options = []
           for c in word:
               if c in leet_map:
                   options.append(leet_map[c])  # Seulement les leet substitutions
               else:
                   options.append([c])  # Consonnes et autres caractères inchangés
           return product(*options)

        input_file = '/tmp/rockyou.txt'
        output_file = 'rockyou_strict_leet.txt'

        with open(input_file, 'r', encoding='latin-1') as infile, open(output_file, 'w', encoding='utf-8') as outfile:
           seen = set()
           for line in infile:
               word = line.strip()
               for variant in leetify_strict(word):
                   leet_word = ''.join(variant)
                   if leet_word not in seen:
                       seen.add(leet_word)
                       outfile.write(leet_word + '\n')

        print("Fichier strictement leetifié généré : rockyou_strict_leet.txt")
      • On lance hashcat pour tenter de cracker le hash :

        hashcat -O -m 1400 -a 0 -o cracked3.txt hash3.txt rockyou_strict_leet.txt
        Élément Description
        -O Active l’optimisation des performances (peut ignorer certaines règles complexes)
        -w 3 Définit une charge de travail GPU élevée (niveau 3 = rapide, mais intensif)
        -m 1400 Spécifie le type de hash : SHA-256
        -a 0 Mode d’attaque : attaque par dictionnaire simple
        hash3.txt Fichier contenant les hashes à casser
        -o cracked3.txt Fichier de sortie : écrit les hashes cassés avec les mots de passe trouvés
        ./rockyou_strict_leet.txt Wordlist personnalisée contenant des mots avec une faute de frappe (1 caractère supprimé)

        Non documenté : Hashcat n'a pas su cracker le hash.

    • On reprend le script remplaçant cette fois le 'a': ['4'] par 'a': ['@'] dans le mapping des substitutions

    • On lance à nouveau hashcat pour tenter de cracker le hash :

      hashcat -O -m 1400 -a 0 -o cracked3.txt hash3.txt rockyou_strict_leet.txt
    • Voici l'output de hashcat:

      OpenCL API (OpenCL 3.0 PoCL 3.1+debian  Linux, None+Asserts, RELOC, SPIR, LLVM 15.0.6, SLEEF, DISTRO, POCL_DEBUG) - Platform #1 [The pocl project]
      ==========================================================================================================================
      Device #1: pthread-haswell-13th Gen Intel(R) Core(TM) i9-13900KF, 30986/62037 MB (8192 MB allocatable), 32MCU,

      Minimum password length supported by kernel: 0
      Maximum password length supported by kernel: 31

      Hashes: 1 digests; 1 unique digests, 1 unique salts
      Bitmaps: 16 bits, 65536 entries, 0x0000ffff mask, 262144 bytes, 5/13 rotates
      Rules: 1

      Optimizers applied:
      Optimized-Kernel,
      Zero-Byte,
      Precompute-Init,
      Early-Skip,
      Not-Salted,
      Not-Iterated,
      Single-Hash,
      Single-Salt,
      Raw-Hash,

      Watchdog: Temperature abort trigger set to 90c

      Host memory required for this attack: 87 MB

      Dictionary cache built:
      Filename..: rockyou_strict_leet.txt,
      Passwords.: 14212481,
      Bytes.....: 138965419,
      Keyspace..: 14212463,
      Runtime...: 0 secs,
      NEW
      [18:26]
      Session..........: hashcat
      Status...........: Cracked
      Hash.Mode........: 1400 (SHA2-256)
      Hash.Target......: 4ac53d04443e6786752ac78e2dc86f60a629e4639edacc6a593...acc30f
      Time.Started.....: Sat Jul 12 18:20:32 2025, (0 secs)
      Time.Estimated...: Sat Jul 12 18:20:32 2025, (0 secs)
      Kernel.Feature...: Optimized Kernel
      Guess.Base.......: File (rockyou_strict_leet.txt)
      Guess.Queue......: 1/1 (100.00%)
      Speed.#1.........: 13256.8 kH/s (6.81ms) @ Accel:1024 Loops:1 Thr:10 Vec:8
      Recovered........: 1/1 (100.00%) Digests (total), 1/1 (100.00%) Digests (new)
      Progress.........: 1310836/14212463 (9.22%)
      Rejected.........: 116/1310836 (0.01%)
      Restore.Point....: 983088/14212463 (6.92%)
      Restore.Sub.#1...: Salt:0 Amplifier:0-1 Iteration:0-1
      Candidate.Engine.: Device Generator
      Candidates.#1....: c@rl0v0n -> ryb@b3
      Hardware.Mon.#1..: Temp: 72c Util: 15%

      Started: Sat Jul 12 18:20:31 2025
      Stopped: Sat Jul 12 18:20:34 2025

      Cette fois le hash est cracké! Le petit malin qui a imaginé ce challenge a été vicieux et a utilisé @ au lieu de 4 et les autres voyelles étaient leetifiées avec des nombres...

    • On vérifie : 

      $ cat cracked3.txt
      4ac53d04443e6786752ac78e2dc86f60a629e4639edacc6a5937146f3eacc30f:unf0rg1v@bl3
      echo -n "unf0rg1v@bl3" | sha256sum
      4ac53d04443e6786752ac78e2dc86f60a629e4639edacc6a5937146f3eacc30f  -

      Troisième hash vaildé!

      🏁 Flag

            • A ce stade nous avons :

              • Hash1 = hyepsi^4B

              • Hash2 = thecowsaysmo

              • Hash3 = unf0rg1v@bl3

            • Il nous reste à reconstituer le mot de passe :

              • Flag format: L3AK{pass1_pass2_pass3}

              • Flag = L3AK{hyepsi^4B_thecowsaysmo_unf0rg1v@bl3}