• STATISTIQUES
  • Il y a eu un total de 1 membres et 4532 visiteurs sur le site dans les dernières 24h pour un total de 4 533 personnes!


    Membres: 2 604
    Discussions: 3 579
    Messages: 32 816
    Tutoriels: 78
    Téléchargements: 38
    Sites dans l'annuaire: 58


  • ANNUAIRE
  • [FR] Le top web
    Nous offrons une sélection la plus large possible de resources webmaster gratuites, hébergement gratuit...
    Webmaster
    [EN] SecurityFocus
    SecurityFocus a été conçu pour faciliter la discussion sur des sujets liés la sécu...
    Vulnérabilités
    [EN] HackQuest
    Logic: 12, JavaScript: 14, Applet: 6, CrackIt: 13, Crypto: 11, Internet: 3, Exploit: 7, Stegano: 12, Flash: 1, Programmi...
    Challenges
    [FR] µContest
    µContest est un site de challenges de programmation, c'est à dire qu'il propose des épreu...
    Hacking
    [FR] Asp-php
    Tutoriaux sur ASP, PHP, ASP.net, XML, SQL, Javascript, HTML, VML - Scripts et ressources pour webmasters - Forums d&#...
    Programmation
    [FR] Secuser
    Actualité de la sécurité informatique, fiches virus et hoax, alertes par email, antivirus gratui...
    Hacking
    [FR] Comment ca marche
     Gratuit et accessible à tous, ce site de communauté permet de se dépanner, se faire aider ...
    Webmaster

  • DONATION
  • Si vous avez trouvé ce site internet utile, nous vous invitons à nous faire un don du montant de votre choix via Paypal. Ce don servira à financer notre hébergement.

    MERCI!




Note de ce sujet :
  • Moyenne : 0 (0 vote(s))
  • 1
  • 2
  • 3
  • 4
  • 5
[Python] La stéganographie BMP
02-07-2013, 13h00 (Modification du message : 02-07-2013, 13h06 par Kiwazaru.)
Message : #1
Kiwazaru Hors ligne
Padawan d'un super escargot
*



Messages : 284
Sujets : 26
Points: 139
Inscription : Mar 2012
[Python] La stéganographie BMP
Yop tout le monde !
Alors voilà, il y a quelques temps j'ai commencé à apprendre le python.
Langage qui pour moi et pour pas mal d'autre est un langage qui nous permet d'écrire des programmes très rapidement en CTF par exemple !
Après une semaine de RTFM et d'apprentissage des bases, j'ai décidé de me lancer dans un projet qui à la base.. ne devait pas en être un Big Grin

La stéganographie BMP Smile
J'avais voulu en faire une épreuve, mais après un fail total de celle-ci (seul Luxerails l'a pown x)), je décide de poster le code commenté.

Le code parle de lui même ! (J'ai essayé de le commenter le plus possible !)

Code PYTHON :

#!/usr/bin/python2.7
# -*- coding: utf-8 -*-
"""
        Usage: {} <options>".format(sys.argv[0]))
        Options:
        -p <picture_container> <file_to_hide> <eof> <xorkey> <output> (Pour coder l'image)
        -u <encoded_picture> <eof> <xorkey> <output> (Pour decoder l'image)
        -ns <port> <eof> <xorkey> <inc> <dec> (Pour lancer le serveur)
        -nc <ip> <port> <picture> <eof> <xorkey> <inc> <dec> (Pour lancer le client)
        --help (to get help)"""

       
"""
Le principe de la stéganographie , globalement est de cacher une donnée , une information dans une autre donnée lambda..
Nous allons voir dans ce code, la stéganographie BMP (Il est aussi possible de le faire pour le PNG, mais ce code n'est pas compatible).
Le but de la steganographie de ce format d'image, est de coder l'image à cacher, dans l'image que nous appellerons contenante.
Pour une image BMP par exemple, son codage est le suivant: R V B Padding (Octet R, Octet V, Octet B, Octet de padding).
Un octet est codé sur 8 bits. Dans ces 8 bits, nous avons un bit de poid fort (MSB) et un bit de poid faible (LSB). Vous vous en douterez,
le LSB aura beaucoup moins d'impact sur la couleur si nous le mondifions, que le MSB !
Le principe de cette stéganographie est donc tout simplement, de coder 8 bits d'un octet de l'image à cacher, sur les LSB de 8 octets de l'image contenante !
Petite dédicace à khaled, on va dire que ce code est sous licence WTFPL hein
"""


import sys, struct, socket


def header(original_picture):

    if original_picture[0:2] != 'BM':
        print "The picture is not a bitmap !"
        sys.exit("System Exit with Error: Bad file !")
   
    # Liste les informations principales du fichier.
    print "- Name of file: " + str(sys.argv[2])
    print "- Type of file: " + original_picture[0:2] + " ( 2 bytes )"
    print "- Size of file: " + str(struct.unpack("<I", original_picture[2:6])[0] / 1000) + " kB (" + str(struct.unpack("<I", original_picture[2:6])[0]) + " bytes)  ( 4 bytes ) "
    print "- Width: " + str(struct.unpack("<I",original_picture[18:22])[0]) + " px ( 4 bytes )"
    print "- Heigth: " + str(struct.unpack("<I", original_picture[22:26])[0]) + " px ( 4 bytes )"
    print "- Compression: " + str(struct.unpack("<I", original_picture[30:34])[0]) + " ( 4 bytes )"
    print "- Horizontal Resolution: " + str(struct.unpack("<I", original_picture[38:42])[0]) + " ( 4 bytes )"
    print "- Vertical Resolution: " + str(struct.unpack("<I", original_picture[42:46])[0]) + " ( 4 bytes )"

def encode(original_picture, hidden_picture, eof_file, xor):
    """ ENCODE THE PICTURE """
   
    # Converti la chaîne en liste.
    hidden_picture = list(hidden_picture)
    original_picture = list(original_picture)
   
    # Padding pour avoir une taille de fichier BMP qui convient.
    hidden_picture += eof_file
    if len(hidden_picture) % 4 != 0:
        hidden_picture += 'F' *  (4 -(len(hidden_picture) % 4)) # On ajoute x* l'octet "F".
   

    # On vérifie la taille des images (*8 car nous allons coder un octet de l'image à cacher sur 8 octets de l'image contenante)
    if len(original_picture) < len(hidden_picture) * 8:
        print "The original picture is too short !"
        sys.exit("Picture too short !")

    # Les variables..
    i = 0 # Offset courant de l'image à cacher
    y = 0 # Offset courant de l'image contenante
    buf = ''.join(hidden_picture)
    hide = ""
    while i < len(buf):
        hide += struct.pack("I", (struct.unpack("I", buf[i:i+4])[0] ^ xor)) # On XOR notre image à cacher.
        i += 4
    hide = list(hide) # On fou notre hide qui contient notre image xoré
    i = 0
    while i < len(hidden_picture):
        key = 0x01 # La clé commence à 0x01 et on applique une opération SHL << 1 pour obtenir les valeurs croissantes -> 0x01 0x02 0x04 0x08 0x10 0x20 0x40 0x80 pour obtenir les bits 1 par 1
        for n in xrange(0, 8):
            original_picture[y] = chr((ord(original_picture[y]) & 0xFE) | ((ord(hide[i]) & key ) >> n) ^ 1) # AND 0xFE est utilisé pour obtenir le LSB de l'octet courant de l'image originale, FE != FF, l'opération OR est utilisée pour placer le bit dans le LSB, le SHR >> n est utilisé pour obtenir un et un seul bit de l'image à cacher.
            # On xor notre bit obtenu de l'octet courant de l'image à cacher et on le XOR par 1 pour l'inverser
            key = key << 1 # On applique une opération SHL pour obtenir une clé de plus en plus grande pour obtenir nos bits dans l'ordre: LSB -> MSB
            y += 1 # On incrémente l'offset y pour coder sur le LSB de l'octet suivant
        i += 1 # Quand nous avons codé un octet de l'image à cacher (for n in xrange(0, 8) on incrémente l'offset i pour passer à l'octet suivant

    return ''.join(original_picture)

def decode(encoded_picture, eof_file, xor):
    """ DECODE THE PICTURE """

    encoded_picture = list(encoded_picture)

    buf = ""
    rFile = "" # L'image décodée sera contenue dans cette variable
    bit_X = [] # Liste des bits (sera utilisé plus tard)
    i = 0
    try:
        while i < len(encoded_picture):
            for x in xrange(0, 4): # Pour pouvoir xor 4 octets par la suite
                for n in xrange(0, 8): # On prend les 8 LSB d'un octet de l'image contenante
                    bit_X.append( str((ord(encoded_picture[i]) & 0x1) ^ 1) ) # On ajoute le bit xoré par 1 pour réinverser l'inversion du codage à bit_X...
                    i += 1 # On incrémente de 1 l'offset i pour obtenir l'octet suivant
                buf += chr(int(''.join(bit_X)[::-1], 2)) # On obtient la valeur ASCII du binaire obten. [::-1] est utilisé pour inverser la chaine puisque nous avons codé LSB -> MSB
                bit_X = []
            buf = struct.unpack("I", buf)[0]
            buf = buf ^ xor # On xor 4 octets pour obtenir le bout d'image complètement décodé // On pourrait faire octet par octet pour éviter la boucle for x in xrange(0, 4).
            buf = struct.pack("I", buf)
            rFile += buf # On ajoute le bout d'image à la variable finale.
            buf = ""
    except:
        """ EXCEPT !"""
    return rFile[:rFile.rfind(eof_file)] # On retourne l'image jusqu'à l'occurence de son EOF, pour ne pas casser l'image

# Cette partie était pour le challenge, le principe est d'envoyer un message codé dans l'image BMP et de faire croire à un envoi d'image
   
def server(src_port, eof_file, xorkey, inc, dec):
    """ SOCKET HERE """
    # On obtient les arguments..
    xorkey = int(xorkey)
    src_port = int(src_port)
    bRecv = b""
    i = 0
    # On défini la partie socket
    #bRecv = sClient.recv(4096)
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
    s.bind(('0.0.0.0', src_port))
    s.listen(5)
    print "Socket listen on port: " + str(src_port)
    sClient, info = s.accept()
    print "Connexion reçue: " + str(info)
    buf = ""
    data = ""
    while True:
        while not "EOF" in buf: # Trick pour éviter les bugs rencontré avec la fonction recv()  On se base sur le fait que le message ne contiendra pas EOF..
            buf = sClient.recv(8048)
            data += buf
        data = data[:len(data) - 3] # On vire l'eof
       
        # Le trick suivant est tout con, mais je le trouve sympa  On pourrait qualifier ça d'une transmition de données chiffrée asymétriquement même si ce n'est pas vraiment
        # le cas. En fait, le principe est de définir des deux coté (client/serveur) une incrémentation de xorkey & une décrémentation de xorkey.
        # Ainsi le programme alternera entre incrémenter la xorkey & la décrémenter, il deviendra alors quasiment impossible à un pirate ayant sniffé le réseau au moment
        # de la transmition, de decoder le message.
        # L'algorithme ci-dessous parle de lui même
        if i == 0:
            xorkey += inc
            data = decode(data[54:], eof_file, xorkey) # On appelle bien evidemment la fonction decode pour décoder le bouzin :p
            i += 1
        else:
            xorkey -= dec
            data = decode(data[54:], eof_file, xorkey) # Same
            i -= 1

        print data # On affiche le message
        data = ""
        buf = ""
    s.close()

def client(dst_ip, dst_port, picture, header_bmp, eof_file, xorkey, inc, dec):
    # On obitent les arguments ..
    xorkey = int(xorkey)
    dst_port = int(dst_port)
    nickname = raw_input("Nickname: ")
    nickname = "[" + nickname + "] : "
    bSend = b""
    i = 0
   
    # On défini la partie socket
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    s.connect((dst_ip, dst_port))
    print "Connected to " + dst_ip + ":" + str(dst_port) + "  -- Linux (CTRL+D) to escape :: Windows (CTRL+C) to escape" # Je ne suis pas sûr des raccourcis x)
    try:
        while True:
            bSend = nickname + raw_input("Post: ")
            if i == 0:
                xorkey += inc
                s.send(header_bmp + encode(picture, bSend, eof_file, xorkey) + "EOF") # On envois le message codé avec "EOF" rajouté à la fin pour le trick anti bug recv() :p
                i += 1
            else:
                xorkey -= dec
                s.send(header_bmp + encode(picture, bSend, eof_file, xorkey) + "EOF") # Same
                i -= 1

    except:
        s.close()
        sys.exit("Socket error")

def usage():
    if len(sys.argv) < 3:
        print ("Usage: {} <options>".format(sys.argv[0]))
        print ("Options:")
        print ("-p <picture_container> <file_to_hide> <eof> <xorkey> <output> (to encode a picture)")
        print ("-u <encoded_picture> <eof> <xorkey> <output> (to decode a picture)")
        print ("-ns <port> <eof> <xorkey> <inc> <dec> (to start server)")
        print ("-nc <ip> <port> <picture> <eof> <xorkey> <inc> <dec> (to start the client)")
        print ("--help (to get help)")
        sys.exit("")

if __name__ == '__main__':

    print sys.version

    if len(sys.argv) < 2:
        usage()

    elif sys.argv[1] == '--help':
        usage()

    elif len(sys.argv) == 7 and sys.argv[1] == '-p': # len(sys.argv) == 6 , si vous lancez sans donner l'emplacement de python.exe !
        #def encode(original_picture, hidden_picture, eof_file, xor):
        try:
            # On get les deux images.
            original = open(sys.argv[2], 'rb')
            original_picture = ''.join(original.readlines())
            original.close()

            hidden = open(sys.argv[3], 'rb')
            hidden_picture = ''.join(hidden.readlines())
            hidden.close()
           
            # On prend le header BMP pour l'écriture en sortie.
            header(original_picture) # On affiche les infos du fichier BMP
            header_bmp = original_picture[:54]
            original_picture = original_picture[54:]


            output_file = open(sys.argv[6], 'wb+')
            output_file.write(header_bmp + encode(original_picture, hidden_picture, sys.argv[4], int(sys.argv[5]))) # On passe les deux images à la fonction encode()
            print "[+] File " + sys.argv[6] + " was encoded !"
            output_file.close()
        except IOError:
            print "No file !"
            sys.exit("IOError")

    elif len(sys.argv) == 6 and sys.argv[1] == '-u': # len(sys.argv) == 5 si vous lancez sans donner l'emplacement de python.exe !
        #def decode(encoded_picture, eof_file, xor):
        try:
            # On get
            encoded_pic = open(sys.argv[2], "rb")
            encoded_picture = ''.join(encoded_pic.readlines())
            encoded_pic.close()
            header(encoded_picture) # On affiche les infos du fichier BMP
            encoded_picture = encoded_picture[54:]


            output_file = open(sys.argv[5], 'wb+')
            output_file.write(decode(encoded_picture, sys.argv[3], int(sys.argv[4]))) # On passe l'image à la fonction decode()
            print "[+] File " + sys.argv[5] + " was decoded !"
            output_file.close()

        except IOError:
            print "No file !"
            sys.exit("IOError")

    elif len(sys.argv) == 7 and sys.argv[1] == '-ns':
        #def server(src_port, eof_file, xorkey, inc, dec):
        server(int(sys.argv[2]), sys.argv[3], int(sys.argv[4]), int(sys.argv[5]), int(sys.argv[6])) # On lance le serveur

    elif len(sys.argv) == 9 and sys.argv[1] == '-nc':
        #def client(dst_ip, dst_port, picture, header_bmp, eof_file, xorkey, inc, dec):
       
        # On obtient les arguments..
        picture = open(sys.argv[4], 'r')
        tPicture = ''.join(picture.readlines())
        header_bmp = tPicture[:54]
        tPicture = tPicture[54:]
        picture.close()
        client(sys.argv[2], int(sys.argv[3]), tPicture, header_bmp, sys.argv[5], int(sys.argv[6]), int(sys.argv[7]), int(sys.argv[8])) # On lance le client

    else:
        usage()
 


Tout les remarques sont les bienvenues ! Je dis sûrement des bêtises dans mon truc et le bitwises operator ne me sont pas encore totalement familier !
Toucher au Kernel, c'est un peut comme se shooter au LSD, on pense pouvoir tout faire mais ça finit souvent mal.
+1 (0) -1 (0) Répondre
02-07-2013, 23h29
Message : #2
oosfalte Hors ligne
Flying Cloud
*



Messages : 47
Sujets : 3
Points: 8
Inscription : Jan 2013
RE: [Python] La stéganographie BMP
Merci, je commence à décortiquer et déjà bien intéressant.
+1 (0) -1 (0) Répondre


Sujets apparemment similaires…
Sujet Auteur Réponses Affichages Dernier message
  [Python]Situer mon niveau. InforMods 19 277 10-11-2016, 00h03
Dernier message: ZeR0-@bSoLu
  [PYTHON] un bot IRC basique darcosion 1 73 13-06-2016, 20h40
Dernier message: Yttrium
  [python] ANBU ::: TCP Session Hunter St0rn 2 139 25-02-2016, 18h45
Dernier message: otherflow
  [Python] Une autre façon de gérer les Virtualenv et Packages thxer 2 35 18-01-2016, 12h06
Dernier message: thxer
  [Python] rot script ark 9 162 08-03-2015, 00h37
Dernier message: ark
  [Python] Todo Manager ark 5 161 03-03-2015, 10h55
Dernier message: ark
  [python] Un décorateur pour inventorier les objets b0fh 1 77 04-12-2014, 17h50
Dernier message: thxer
  [python] UPnP Scanner St0rn 2 96 29-10-2014, 14h50
Dernier message: St0rn
  [python] Buffer Overflow : EBP et EIP St0rn 0 83 25-10-2014, 12h58
Dernier message: St0rn
  [Python] QuickHex thxer 9 160 15-08-2014, 20h26
Dernier message: sakiir

Atteindre :


Utilisateur(s) parcourant ce sujet : 1 visiteur(s)
N-PN
Accueil | Challenges | Tutoriels | Téléchargements | Forum | Retourner en haut