Steganografian demostraatio

cMaster 11.03.08 22:32

Tällä pätkällä voit piilottaa kamaa *.jpg kuviin :)

 Tekstiversio  Arvo: -6 (10 ääntä)  Äänestä: +  -
<?php

/*
    ** //¯¯\\__ KÄYTTÖ __//¯¯\\ **
    stegano_encode( $text, $jpg, $pack = true, $pw = "", $debug = false );
    $text - Tähän heität tekstiä jonka haluat piilottaa
    $jpg - Mihin kuvaan tieto piilotetaan
    $pack - Haluatko pakata tiedon? (oletus = true)
    $pw - Aseta salasana (oletus = ei salasanaa)
    $debug - Jos haluat saada lisätietoa (oletus = false)

    ** //¯¯\\__ HUOMIOI __//¯¯\\ **
    Tee aina varakopio kuvasta ennen "piilotusta".
    Kuvan laatu saattaa kärsiä huomattavasti ...
    Älä kaytä pakkausta, jos tietosi on alle 24 merkkiä pitkä!

    ** //¯¯\\__ TEKIJÄNOIKEUS __//¯¯\\ **
    Jos käytät tätä skriptiä jätä tämä kommentti siihen.
    Kirjoittanut: Joonas Lauhala - 2008 :)

    ** //¯¯\\__ MUUTA TIETOA __//¯¯\\ **
    Purkutoimintoa en vielä ole ehtinyt kirjoittaa :(

*/


function stegano_encode( $text, $jpg, $pack = true, $pw = "", $debug = false ){

    // Jos teksti ei ole tyhjä - jatka...
    if( !empty( $text ) ){

        // Jos salasana ei ole tyhjä
        if( !empty( $pw ) ){

            // Häshätään salasana md5:llä
            $pw = md5( $pw );

            // Asetataan "aseta" lippu :)
            $set_pw = true;

        }

        // Jos $pack on tosi
        if( $pack ){

            // Pakkaa tieto gunzipillä :)
            $text = gzcompress( $text, 9 );

        }

        // Hanki tekstin pituus
        $length = strlen( $text );

        // Jos "aseta" lippu on tosi
        if( $set_pw === true ){

            // Iteroidaan joka merkki läpi...
            for( $l = 0; $l < $length; $l++ ){

                // Lasketaan avain
                $key = ord( $pw[$l % 32] ) * ( $l + 1 );

                // Luodaan "merkkikoodi"
                $char = ord( $text[$l] ) + $length;

                // Salataan Xor:lla :)
                $text[$l] = chr( $char ^ $key );

            }

        }

        // Kuinka monta nollatavua on ennen tietoa?
        $header_size = 4;

        // Laske tarvittavat bitit + nollatavujen määrä
        $allocate = ( $length + $header_size ) * 8;

        // Jos tiedosto on olemassa ja pääte on .jpg - jatka...
        if( file_exists( $jpg ) && substr( strtolower( $jpg ), -4, 4 ) === ".jpg" ){

            // Hanki kuvan sisältö
            $jpgfile = file_get_contents( $jpg );

            // Tähän kohtaan voit laittaa tarkistuksen onko kuva
            // todella JPG-kuva :)

            // Kuinka iso kuvatiedosto on kyseessä
            $filesize = strlen( $jpgfile );

            // Jos tiedon pituus on pienempi kuin kuva - 256
            // -256 on siksi ettet vain korvaa kuvan "headeriä"
            if( $allocate < ( $filesize - 256 ) ){

                // Ota merkkejä kuvan lopusta
                $contents = substr( $jpgfile, -$allocate );

                // Iteroi teksti, taas :)
                for( $l = 0; $l < ( $length + $header_size ); $l++ ){

                    // Muunna teksti binaariksi
                    $bin_text = sprintf( "%08b", ord( $text[$l] ) );

                    // Käy bitit lävitse
                    for( $x = 0; $x < 8; $x++ ){

                        // Muunna kuvadata binaariksi
                        $bin_jpg = sprintf( "%08b", ord( $contents[$offset+$x] ) );

                        // Debuggaus päällä?
                        if( $debug ){

                            // Kirjaa kuvan data muuttujaan
                            $dbg_data .= chr( $bin_jpg );

                        }

                        // Onko nollatavujen aika?
                        if( $l < $header_size ){

                            // Asetetaan nollatavu
                            $bin_text[$x] = "0";

                        }

                        // Korvataan viimeinen bitti tekstin bitillä ...
                        $data .= chr( substr( $bin_jpg, 0, 7 ) . $bin_text[$x] );

                    }

                    // Alkukohta + 8
                    $offset += 8;

                }

                // Siirretään muunneltu data kuvadatan paikalle
                $jpgfile = substr( $jpgfile, 0, $filesize - $allocate ) . $data;

                // Debuggaus päällä?
                if( $debug ){

                    // Debuggaus tiedoston nimi
                    $dbg_name = basename( $jpg ) . "_debug.txt";

                    // Kahva filuun
                    $handle = fopen( $dbg_name, "w" );

                    // Kirjoitetaan tiedot filuun
                    fwrite( $handle, "Original image data was:\r\n" . $dbg_data .
                    "\r\n\r\nNew image data is:\r\n" . $data );

                    // Suljetaan kahva
                    fclose( $handle );

                }

                // Avataan itse kuvatiedoto
                $handle = fopen( $jpg, "w" );

                // Voidaanko kahvaa käyttää?
                if( $handle ){

                    // Kirjoita kuvatiedosto
                    fwrite( $handle, $jpgfile );

                }else{

                    // Palauta virhekoodi 3
                    // Tiedostoon ei voitu kirjoittaa
                    return 3;

                }

                // Suljetaan kahva - varmuudeksi :)
                fclose( $handle );

            }else{

                // Palautetaan virhekoodi 2
                // Teksti on liian pitkä
                return 2;

            }

        }else{

            // Palautetaan virhekoodi 1
            // Kuvatiedostoa ei ole tai pääte on väärä
            return 1;

        }

    }else{

        // Palautetaan virhekoodi 0
        // Teksti on tyhjä!
        return 0;

    }

}

/*

Raportoikaa virheistä niin korjailen kyllä.
Terveisin: Joonas (cMaster) :)

Käyttöesimerkki:

stegano_encode( "Piilota minut kuvaan :)", "kuva.jpg", false );

TAI

stegano_encode( "Piilota tämäkin kuvaan :)", "kuva1.jpg", true, "Salasanani" );

*/


?>

editoitu: 16:24 12.3.08
T.M. 16:06 12.3.08 
mites sä oot tän toiminnan testannut josset oo purkutoimintoo tehny ?

$bin_jpg = sprintf( "%08b", ord( $contents[$offset+$x] ) );
...
chr( $bin_jpg );
wtf?


$data .= chr( substr( $bin_jpg, 0, 7 ) . $bin_text[$x] );
$jpgfile = substr( $jpgfile, 0, $filesize - $allocate ) . $data;
WTF.

Koodin perusteella voisin melkein jopa sanoa ettei tämä toimi ollenkaan o_O

Voisitko vielä selostaa miten tuo oikeasti toimii? Koodin kommentit perseestä, ne lähinnä selostavat mitä se yksi koodirivi tekee, tyyliin:
                    // Alkukohta + 8
                    $offset += 8;
joka ei hyödytä ketään...

--

Miinus kaikesta yllä mainituista syistä. Tee toimiva salaus/purku niin plussaa tulee :)
cMaster 18:23 12.3.08 
T.M. kirjoitti:
mites sä oot tän toiminnan testannut josset oo purkutoimintoo tehny ?


Kyllä on testattu, koska purkutoiminto kyllä on mutta se on aivan liian manuaalinen "toiminnoksi",
jotenka sille pitää tehdä vielä paljonkin että siitä tulee toiminto.

T.M. kirjoitti:
Miinus kaikesta yllä mainituista syistä. Tee toimiva salaus/purku niin plussaa tulee :)


Ei mullakaan aika kaikkeen aina riitä :(
Ztane 10:40 13.3.08 
Kai tiedät mitä steganografia on? Piilotetaan siis legitiimin näköiseen viestiin jotain salakirjoitusta? "Jpeg-kuva", joka steganografian soveltamisen jälkeen ulvottaa gimppiä viestillä "unsupported marker type 0x75" on muutaman valovuoden päässä steganografiasta.