From 0318bbbf335d58d735a228a65d85315d7f1e5441 Mon Sep 17 00:00:00 2001 From: BlackLight Date: Mon, 13 Jul 2009 18:55:12 +0200 Subject: [PATCH] lulz --- AUTHORS | 4 ++ BUGS | 5 +++ INSTALL | 18 ++++++++ LICENCE | 30 +++++++++++++ Makefile | 30 +++++++++++++ README | 21 +++++++++ TODO | 2 + compress.cpp | 78 +++++++++++++++++++++++++++++++++ decode.cpp | 86 ++++++++++++++++++++++++++++++++++++ encode.cpp | 120 +++++++++++++++++++++++++++++++++++++++++++++++++++ jastegal.cpp | 119 ++++++++++++++++++++++++++++++++++++++++++++++++++ jastegal.h | 73 +++++++++++++++++++++++++++++++ utils.cpp | 111 +++++++++++++++++++++++++++++++++++++++++++++++ 13 files changed, 697 insertions(+) create mode 100644 AUTHORS create mode 100644 BUGS create mode 100644 INSTALL create mode 100644 LICENCE create mode 100644 Makefile create mode 100644 README create mode 100644 TODO create mode 100644 compress.cpp create mode 100644 decode.cpp create mode 100644 encode.cpp create mode 100644 jastegal.cpp create mode 100644 jastegal.h create mode 100644 utils.cpp 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; +} +