commit 0318bbbf335d58d735a228a65d85315d7f1e5441 Author: BlackLight Date: Mon Jul 13 18:55:12 2009 +0200 lulz diff --git a/AUTHORS b/AUTHORS new file mode 100644 index 0000000..d912fda --- /dev/null +++ b/AUTHORS @@ -0,0 +1,4 @@ +Author: BlackLight +Mail: blacklight@autistici.org +Web: http://0x00.ath.cx | http://blacklight.gotdns.org + diff --git a/BUGS b/BUGS new file mode 100644 index 0000000..bc4ae0c --- /dev/null +++ b/BUGS @@ -0,0 +1,5 @@ +Sometimes the last two bytes or the last byte of the text is truncated +in decode operations. I don't know if it's my fault, as this bug seems +to happen almost in random strings of random length, or zLib's fault. +I'll try to fix anyway. + diff --git a/INSTALL b/INSTALL new file mode 100644 index 0000000..5c226d0 --- /dev/null +++ b/INSTALL @@ -0,0 +1,18 @@ +* PREREQUISITES + +> You must have CImg libraries installed on your + system in order to compile and use Jastegal. These libraries are used for a + high-level wrapping of image managing. + +> You also must have zlib installed on your system. zlib is installed almost + anywhere, and it's use by Jastemal for compression/uncompression operations. + + +* INSTALLATION + +> To install Jastegal on your system you need, of course, g++ and gmake already + installed. Then, just type: + + $ make + % make install + diff --git a/LICENCE b/LICENCE new file mode 100644 index 0000000..5c5072d --- /dev/null +++ b/LICENCE @@ -0,0 +1,30 @@ +The files in this directory and elsewhere which refer to this LICENCE +file are part of Jastegal (Just Another Steganography algorithm) + + Copyright (C) 2009 BlackLight + +Jastegal is free software; you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free +Software Foundation; either version 3 or (at your option) any later +version. + +Jastegal is distributed in the hope that it will be useful, but WITHOUT +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. + +You should have received a copy of the GNU General Public License along +with Jastegal; if not, write to the Free Software Foundation, Inc., +59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + +As a special exception, if other files instantiate templates or use +macros or inline functions from these files, or you compile these +files and link them with other works to produce a work based on these +files, these files do not by themselves cause the resulting work to be +covered by the GNU General Public License. However the source code for +these files must still be made available in accordance with section (3) +of the GNU General Public License. + +This exception does not invalidate any other reasons why a work based on +this file might be covered by the GNU General Public License. + diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..ce6128b --- /dev/null +++ b/Makefile @@ -0,0 +1,30 @@ +CXX=g++ +CFLAGS=-Wall -pedantic +LDFLAGS=-lX11 -lpthread -lm -lz +INSTALLDIR=/usr/local + +NAME=jastegal +FILES=utils.o jastegal.o encode.o decode.o compress.o + +ifeq (${DEBUG},1) + CFLAGS += -g3 +endif + +all: $(FILES) + ${CXX} ${LDFLAGS} -o ${NAME} ${FILES} + +$(FILES): $(FILES:.o=.cpp) + ${CXX} ${CFLAGS} -c $*.cpp + +install: + mkdir -p ${INSTALLDIR}/bin + install -m 0755 ${NAME} ${INSTALLDIR}/bin + +clean: + rm ${FILES} + rm ${NAME} + +uninstall: + rm -f ${INSTALLDIR}/bin/${NAME} + + diff --git a/README b/README new file mode 100644 index 0000000..d13390d --- /dev/null +++ b/README @@ -0,0 +1,21 @@ +Jastegal (Just Another Steganography Algorithm) v.0.1b +c0ded by BlackLight + +Usage: ./jastegal [-d|-e] <-i image file> [-o output image file] [-f file to be steganographied] + +-d: Perform a decoding from an image +-e: Perform an encoding to an image +-i: Specify the input image to be processed. In case of decoding, the content of this file will be de-steganographied, + while in case of encoding this is the image to steganography from +-o: Specify the output image. This parameter is mandatory in encoding phase, as it specifies the file name containing + the image with the steganographied data +-f: Specify, in encoding phase, the file containing data to be steganographied. If this option is not specified, the + data will be gathered via stdin + +Examples: + jastegal -e -i input_image.png -o output_image.png -f file.txt + This will encode the data in file.txt using input_image.png as image, and putting the output in output_image.png + + jastegal -d -i input_image.png + This will decode the data in input_image.png to stdout + diff --git a/TODO b/TODO new file mode 100644 index 0000000..49378d1 --- /dev/null +++ b/TODO @@ -0,0 +1,2 @@ +Support for base64 output and text cryptography (coming, I hope, *VERY* soon). + diff --git a/compress.cpp b/compress.cpp new file mode 100644 index 0000000..32d201d --- /dev/null +++ b/compress.cpp @@ -0,0 +1,78 @@ +/* + * jastegal.h + * + * The files in this directory and elsewhere which refer to this LICENCE + * file are part of Jastegal (Just Another Steganography algorithm) + * + * Copyright (C) 2009 BlackLight + * + * Jastegal is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 3 or (at your option) any later + * version. + * + * Jastegal is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License along + * with Jastegal; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * As a special exception, if other files instantiate templates or use + * macros or inline functions from these files, or you compile these + * files and link them with other works to produce a work based on these + * files, these files do not by themselves cause the resulting work to be + * covered by the GNU General Public License. However the source code for + * these files must still be made available in accordance with section (3) + * of the GNU General Public License. + * + * This exception does not invalidate any other reasons why a work based on + * this file might be covered by the GNU General Public License. + */ + +#include +#include +#include + +using namespace std; + +char* zCompress (char* uncompressed, unsigned int uLen, unsigned int &cLen) { + char *compressed = new char[uLen+10]; + + if (!compressed) + return NULL; + + if (compress((Bytef*) compressed, (uLongf*) &cLen, (Bytef*) uncompressed, uLen) < 0) + return NULL; + + return compressed; +} + +char* zUncompress (char* compressed, unsigned int cLen, unsigned int &uLen) { + uLen = cLen; + int ret = 4; + char *uncompressed = NULL; + + while ((uLen < 4000000) && (ret != Z_OK)) { + if (uncompressed) + delete [] uncompressed; + + uncompressed = new char[uLen+10]; + + if (!uncompressed) + return NULL; + + ret = uncompress((Bytef*) uncompressed, (uLongf*) &uLen, (Bytef*) compressed, cLen); + + if (ret == Z_MEM_ERROR || ret == Z_BUF_ERROR) + return NULL; + + if (ret != Z_OK) + uLen *= 2; + } + + return uncompressed; +} + diff --git a/decode.cpp b/decode.cpp new file mode 100644 index 0000000..feab77e --- /dev/null +++ b/decode.cpp @@ -0,0 +1,86 @@ +/* + * decode.cpp + * + * The files in this directory and elsewhere which refer to this LICENCE + * file are part of Jastegal (Just Another Steganography algorithm) + * + * Copyright (C) 2009 BlackLight + * + * Jastegal is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 3 or (at your option) any later + * version. + * + * Jastegal is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License along + * with Jastegal; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * As a special exception, if other files instantiate templates or use + * macros or inline functions from these files, or you compile these + * files and link them with other works to produce a work based on these + * files, these files do not by themselves cause the resulting work to be + * covered by the GNU General Public License. However the source code for + * these files must still be made available in accordance with section (3) + * of the GNU General Public License. + * + * This exception does not invalidate any other reasons why a work based on + * this file might be covered by the GNU General Public License. + */ + +#include + +#include +#include "jastegal.h" + +using namespace std; +using namespace cimg_library; + +string steganoDecode (string inImg) { + CImg img(inImg.c_str()); + rgb header[8]; + string content; + unsigned int uLen, size = 0; + + for (unsigned int i=0; i < 8; i++) { + header[i].r = img[3*i]; + header[i].g = img[3*i + 1]; + header[i].b = img[3*i + 2]; + } + + for (unsigned int i=0; i < 8; i++) { + size |= ((header[i].r & 0x3) << (i*4)); + size |= ((header[i].b & 0x3) << ((i*4)+2)); + } + + for (unsigned int i=6*sizeof(unsigned int); i < 6*(size + sizeof(unsigned int)); i+=6) { + rgb couple[2]; + u8 buf = 0; + + for (unsigned int j=0; j<2; j++) { + couple[j].r = img[i + 3*j]; + couple[j].g = img[i + 3*j + 1]; + couple[j].b = img[i + 3*j + 2]; + } + + buf = + ( ((couple[0].r & 0x3) << 6) | + ((couple[0].b & 0x3) << 4) | + ((couple[1].r & 0x3) << 2) | + ((couple[1].b & 0x3)) ); + + content += buf; + } + + char *uncompressed = zUncompress((char*) content.c_str(), size, uLen); + + if (!uncompressed) + return string(""); + + return string(uncompressed); +} + diff --git a/encode.cpp b/encode.cpp new file mode 100644 index 0000000..0410beb --- /dev/null +++ b/encode.cpp @@ -0,0 +1,120 @@ +/* + * encode.cpp + * + * The files in this directory and elsewhere which refer to this LICENCE + * file are part of Jastegal (Just Another Steganography algorithm) + * + * Copyright (C) 2009 BlackLight + * + * Jastegal is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 3 or (at your option) any later + * version. + * + * Jastegal is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License along + * with Jastegal; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * As a special exception, if other files instantiate templates or use + * macros or inline functions from these files, or you compile these + * files and link them with other works to produce a work based on these + * files, these files do not by themselves cause the resulting work to be + * covered by the GNU General Public License. However the source code for + * these files must still be made available in accordance with section (3) + * of the GNU General Public License. + * + * This exception does not invalidate any other reasons why a work based on + * this file might be covered by the GNU General Public License. + */ + +#include + +#include +#include +#include + +#include "jastegal.h" + +using namespace std; +using namespace cimg_library; + +int steganoEncode (string inImg, string outImg, string fname) { + CImg img(inImg.c_str()); + string::iterator ch; + string content = fileContent(fname); + + unsigned int i, j, k, cLen, size = (fname.empty()) ? content.size() : fileSize(fname); + char *compressed = zCompress((char*) content.c_str(), size, cLen); + + cout << "Working...\n"; + + if (!compressed) + return 1; + + if ((unsigned int) (6*img.dimx()*img.dimy()) <= cLen) { + cerr << "Error: file " << fname << " is too long to be steganographied inside image " << inImg << endl; + return 1; + } + + u8 *buf = new u8[sizeof(unsigned int)]; + memcpy (buf, &size, sizeof(unsigned int)); + + for (i=0; i < 6*sizeof(unsigned int); i+=6) { + unsigned int k = ((int) i/6); + + buf[k] = ( + ((buf[k] & 0x03) << 6) | + ((buf[k] & 0x0c) << 2) | + ((buf[k] & 0x30) >> 2) | + ((buf[k] & 0xc0) >> 6)); + + vector sizebits = bitsplit(buf[k]); + + for (j=0; j < sizebits.size(); j+=2) { + unsigned int index; + u8 operand = (sizebits[j] << 1) | sizebits[j+1]; + + switch (j) { + case 0: index = i ; break; + case 2: index = i+2; break; + case 4: index = i+3; break; + case 6: index = i+5; break; + } + + img[index] = ((img[index] & 0xfc) | operand); + } + } + + //for (i=6*sizeof(unsigned int), ch = content.begin(); ch < content.end(); i+=6, ch++) { + for (i=6*sizeof(unsigned int), k=0; k < cLen; i+=6, k++) { + vector bits = bitsplit(compressed[k]); + + for (j=0; j < bits.size(); j+=2) { + unsigned int index; + u8 operand = (bits[j] << 1) | bits[j+1]; + + switch (j) { + case 0: index=i ; break; + case 2: index=i+2; break; + case 4: index=i+3; break; + case 6: index=i+5; break; + } + + img[index] = (img[index] & 0xfc) | operand; + } + } + + img.save(outImg.c_str()); + img.clear(); + + if (compressed) + delete [] compressed; + + return 0; +} + diff --git a/jastegal.cpp b/jastegal.cpp new file mode 100644 index 0000000..2846354 --- /dev/null +++ b/jastegal.cpp @@ -0,0 +1,119 @@ +/* + * jastegal.cpp + * + * The files in this directory and elsewhere which refer to this LICENCE + * file are part of Jastegal (Just Another Steganography algorithm) + * + * Copyright (C) 2009 BlackLight + * + * Jastegal is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 3 or (at your option) any later + * version. + * + * Jastegal is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License along + * with Jastegal; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * As a special exception, if other files instantiate templates or use + * macros or inline functions from these files, or you compile these + * files and link them with other works to produce a work based on these + * files, these files do not by themselves cause the resulting work to be + * covered by the GNU General Public License. However the source code for + * these files must still be made available in accordance with section (3) + * of the GNU General Public License. + * + * This exception does not invalidate any other reasons why a work based on + * this file might be covered by the GNU General Public License. + */ + +#include + +#include +#include + +#include "jastegal.h" + +using namespace std; +using namespace cimg_library; + +int main (int argc, char **argv) { + int ch; + string inImg, outImg, fname; + action act = undef; + + while ((ch=getopt(argc,argv,"edi:o:f:"))>0) { + switch (ch) { + case 'i': + inImg = string(optarg); + break; + + case 'o': + outImg = string(optarg); + break; + + case 'd': + if (act != undef) { + cerr << "Error: you can use a flag between -d (decode) and -e (encode) a time\n\n"; + printHelp(argv[0]); + return 1; + } + + act = decode; + break; + + case 'e': + if (act == decode) { + cerr << "Error: you can use a flag between -d (decode) and -e (encode) a time\n\n"; + printHelp(argv[0]); + return 1; + } + + act = encode; + break; + + case 'f': + fname = string(optarg); + break; + } + } + + if (act == undef) { + cerr << "Error: you must specify an action between decoding (-d) and encoding (-e)\n\n"; + printHelp(argv[0]); + return 1; + } + + if (inImg.empty()) { + printHelp(argv[0]); + return 1; + } + + if (act == encode) { + if (outImg.empty()) { + cerr << "Error: you must specify a file name for the output image using -o option when encoding\n\n"; + printHelp(argv[0]); + return 1; + } + + if (fname.empty()) + cout << "Enter the input message to be steganographied [CTRL+D to end]:\n"; + + if (steganoEncode (inImg, outImg, fname)) { + cerr << "There was an unrecoverable error while processing the image. Exiting...\n"; + return 1; + } + + cout << "The steganographied output was successfully written to " << outImg << endl; + } else { + cout << steganoDecode(inImg) << endl; + } + + return 0; +} + diff --git a/jastegal.h b/jastegal.h new file mode 100644 index 0000000..3a846b6 --- /dev/null +++ b/jastegal.h @@ -0,0 +1,73 @@ +/* + * jastegal.h + * + * The files in this directory and elsewhere which refer to this LICENCE + * file are part of Jastegal (Just Another Steganography algorithm) + * + * Copyright (C) 2009 BlackLight + * + * Jastegal is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 3 or (at your option) any later + * version. + * + * Jastegal is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License along + * with Jastegal; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * As a special exception, if other files instantiate templates or use + * macros or inline functions from these files, or you compile these + * files and link them with other works to produce a work based on these + * files, these files do not by themselves cause the resulting work to be + * covered by the GNU General Public License. However the source code for + * these files must still be made available in accordance with section (3) + * of the GNU General Public License. + * + * This exception does not invalidate any other reasons why a work based on + * this file might be covered by the GNU General Public License. + */ + +#ifndef __JASTEGAL_H +#define __JASTEGAL_H + +#ifndef __cplusplus +#error "You need a C++ compiler to compile Jastegal" +#endif + +#include +#include + +#define JASTEGAL_VERSION "0.1b" + +typedef unsigned char u8; +typedef enum { undef, encode, decode } action; + +typedef struct { + u8 r; + u8 g; + u8 b; +} rgb; + +int steganoEncode (std::string inImg, std::string outImg, std::string fname = ""); + +std::string steganoDecode (std::string inImg); + +std::vector bitsplit (u8 data); + +unsigned int fileSize (std::string fname); + +std::string fileContent (std::string fname); + +void printHelp (std::string arg); + +char* zCompress (char* uncompressed, unsigned int uLen, unsigned int &cLen); + +char* zUncompress (char* compressed, unsigned int cLen, unsigned int &uLen); + +#endif + diff --git a/utils.cpp b/utils.cpp new file mode 100644 index 0000000..24a8761 --- /dev/null +++ b/utils.cpp @@ -0,0 +1,111 @@ +/* + * utils.cpp + * + * The files in this directory and elsewhere which refer to this LICENCE + * file are part of Jastegal (Just Another Steganography algorithm) + * + * Copyright (C) 2009 BlackLight + * + * Jastegal is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 3 or (at your option) any later + * version. + * + * Jastegal is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License along + * with Jastegal; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * As a special exception, if other files instantiate templates or use + * macros or inline functions from these files, or you compile these + * files and link them with other works to produce a work based on these + * files, these files do not by themselves cause the resulting work to be + * covered by the GNU General Public License. However the source code for + * these files must still be made available in accordance with section (3) + * of the GNU General Public License. + * + * This exception does not invalidate any other reasons why a work based on + * this file might be covered by the GNU General Public License. + */ + +#include +#include + +#include "jastegal.h" +using namespace std; + +vector bitsplit (u8 data) { + unsigned int size = sizeof(data)*8; + u8* bits = new u8[size+1]; + + for (int i=size-1; i>=0; i--) + bits[size-i-1] = (data & (1 << i)) >> i; + + vector v; + v.assign(bits, bits+size); + delete [] bits; + return v; +} + +unsigned int fileSize (string fname) { + ifstream in(fname.c_str()); + + if (!in) + return -1; + + in.seekg(0, ios::end); + unsigned int size = in.tellg(); + in.close(); + return size; +} + +string fileContent (string fname) { + if (!fname.empty()) { + char *buf = NULL; + ifstream in(fname.c_str()); + + if (!in) + return string(""); + + unsigned int size = fileSize(fname); + buf = new char[size]; + + if (!buf) + return string(""); + + in.read(buf,size); + in.close(); + return string(buf); + } else { + string content, line; + + while (getline(cin,line)) + content.append(line); + + return content; + } +} + +void printHelp (string arg) { + cerr << "Jastegal (Just Another Steganography Algorithm) v." << JASTEGAL_VERSION << endl + << "c0ded by BlackLight " << endl << endl + << "Usage: " << arg << " [-d|-e] <-i image file> [-o output image file] [-f file to be steganographied]" << endl << endl + << "-d:\t\tPerform a decoding from an image" << endl + << "-e:\t\tPerform an encoding to an image" << endl + << "-i:\t\tSpecify the input image to be processed. In case of decoding, the content of this file will be de-steganographied," << endl + << "\t\twhile in case of encoding this is the image to steganography from" << endl + << "-o:\t\tSpecify the output image. This parameter is mandatory in encoding phase, as it specifies the file name containing" << endl + << "\t\tthe image with the steganographied data" << endl + << "-f:\t\tSpecify, in encoding phase, the file containing data to be steganographied. If this option is not specified, the" << endl + << "\t\tdata will be gathered via stdin" << endl << endl + << "Examples:" << endl + << "\tjastegal -e -i input_image.png -o output_image.png -f file.txt" << endl + << "\tThis will encode the data in file.txt using input_image.png as image, and putting the output in output_image.png" << endl << endl + << "\tjastegal -d -i input_image.png" << endl + << "\tThis will decode the data in input_image.png to stdout" << endl; +} +