Outils d'utilisateurs

Outils du Site


hackingweek_2014:crypto:crypto3

Différences

Cette page vous donne les différences entre la révision choisie et la version actuelle de la page.

Lien vers cette vue

hackingweek_2014:crypto:crypto3 [2014/03/03 02:11]
ganapati
hackingweek_2014:crypto:crypto3 [2017/04/09 15:33] (Version actuelle)
Ligne 1: Ligne 1:
 **Enoncé :** **Enoncé :**
  
 +{{:hackingweek_2014:crypto:lena.png?200|}}
  
 **Solution :** **Solution :**
 +
 +Après analyse rapide (hexdump, etc) pas de données cachées dans un padding ou autre.
 +L'image est un png, donc sans compression, de plus, lena.png est souvent utilisée comme exemple en stéganographie pour le lsb.
 +
 +On commence par rechercher l'image originale en l'uploadant sur google image (1 seul résultat) :
 +
 +{{:hackingweek_2014:crypto:lenaoriginal.png?200|}}
 +
 +On utilise la commande compare d'imagemagick pour détecter les pixels différents :
 +
 +compare ./lena.png ./lenaOriginal.png ./lenaDiff.png
 +
 +Le résultat montre un motif régulier de différences :
 +
 +{{:hackingweek_2014:crypto:lenadiff.png?200|}}
 +
 +(pixel rouge = pixel différent entre l'image de l'épreuve et l'image originale)
 +
 +Le motif est le suivant :
 +  * valeur rouge
 +  * 3px plus loin : valeur vert
 +  * 3 px plus loin : valeur bleu
 +  * 4 px de décallage
 +  * etc
 +
 +petit script qui récupère les 4 bits de poids faible de chaque couleur et les rassemble 2 par 2 :
 +
 +<code Python>
 +#!/usr/bin/env python
 +# encoding: utf-8
 +
 +import Image
 +import argparse
 + 
 +def get_value(challenge):
 +    picture = Image.open(challenge)
 +    (width, height) = picture.size
 +    challenge = picture.load()
 +
 +    # Flatten 2d array (easier to parse after)
 +    flatten_array = []
 +    for y in range(0,height):
 +        for x in range(0, width):
 +            flatten_array.append(challenge[x,y])
 +
 +    response = ""
 +    color_index = 0
 +    pixel_counter = 0
 +    index = 0
 +    byte = ""
 +    while index < len(flatten_array):
 +        
 +        binary_color = bin(flatten_array[index][color_index])
 +        r = "%s" % binary_color
 +        r = r[2:]
 +        while len(r) < 8:
 +            r = "0" + r
 +        if byte == "":
 +            byte = r[4:]
 +        else:
 +            byte = r[4:] + byte
 +            response = response + byte
 +            byte = ""
 +
 +
 +        # Switch color to check
 +        color_index = color_index + 1
 +        if color_index > 2:
 +            color_index = 0
 +
 +        # Change pixel to check
 +        index = index + 3
 +        pixel_counter = pixel_counter + 1
 +        if pixel_counter > 2:
 +            pixel_counter = 0
 +            index = index + 1
 +
 +    s = response
 +    print ''.join([chr(int(s[8*i:8*i+8], 2)) for i in range(len(s) / 8)])
 +
 +if __name__ == '__main__':
 +    parser = argparse.ArgumentParser(description='Simple steg tool)')
 +    parser.add_argument("-c", action="store", dest="challenge", help="input file", required=True)
 +    command = parser.parse_args()
 +    
 +    get_value(command.challenge)
 +</code>
 +
 + ganapati@goa:~/tools/stegano$ ./sploit.py -c lena.png > output
 + ganapati@goa:~/tools/stegano$ file ./output
 + ./output: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), for GNU/Linux 2.6.32, dynamically linked (uses shared libs), stripped
 +
 +Bingo, le fichier est reconnu comme un executable ELF
 +
 + ganapati@goa:~/tools/stegano$ chmod +x ./output
 + ganapati@goa:~/tools/stegano$ ./output
 + Enter input:
 + foobar
 + Wrong input
 +
 +Il faut reverse l'ELF pour savoir quel est l'entrée attendue.
 +
 +On remarque dans la string suivante dans le bin : 
 + ############ #@#   # ## #   # # ## ##### # ##         ## ##### #### #   #   ## # # ### ##   #   # ## ### #$# ############
 +
 +Le binaire place un curseur au niveau du '@', et la victoire est assurée si le curseur atteint le '$'. L'entrée passée permet de se déplacer dans la chaine. Selon le caractère rencontré, le curseur est déplacé d'un offset particulier :
 +  * caractère 'n' : offset -12
 +  * caractère 's' : offset +12
 +  * caractère 'e' : offset +1
 +  * caractère 'w' : offset -1
 +
 +Tout autre caractère fait sortir du programme. De même, on ne continue que si le curseur se trouve sur un ' ', un '#' renvoyant à la fin du programme.
 +
 +On devine alors (d'après les nsew => North / South / East / West, et les offsets de déplacement) que l'on est en présence d'un labyrinthe de 11x11 cases.
 +
 +(j'ai remplacé les # par des blocks pour la lisibilité)
 +
 + ███████████
 + █ █@█   █ █
 + █ █   █ █ █
 + █ █████ █ █
 + █         █
 + █ █████ ███
 + █ █   █   █
 + █ █ █ ███ █
 + █   █   █ █
 + █ ███ █$█ █
 + ███████████
 +
 +après avoir visualisé le chemin, on peut entrer la réponse :
 +<code>
 +seeneessswwwwwwsssseenneessees
 +</code>
hackingweek_2014/crypto/crypto3.1393809078.txt.gz · Dernière modification: 2017/04/09 15:33 (modification externe)