Cette page vous donne les différences entre la révision choisie et la version actuelle de la page.
hackingweek_2014:crypto:crypto3 [2014/03/03 21:22] ganapati |
hackingweek_2014:crypto:crypto3 [2017/04/09 15:33] (Version actuelle) |
||
---|---|---|---|
Ligne 8: | Ligne 8: | ||
L'image est un png, donc sans compression, de plus, lena.png est souvent utilisée comme exemple en stéganographie pour le lsb. | 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 uploadant sur google image l'image (1 seul résultat) : | + | On commence par rechercher l'image originale en l'uploadant sur google image (1 seul résultat) : |
{{:hackingweek_2014:crypto:lenaoriginal.png?200|}} | {{:hackingweek_2014:crypto:lenaoriginal.png?200|}} | ||
Ligne 28: | Ligne 28: | ||
* 4 px de décallage | * 4 px de décallage | ||
* etc | * 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> |