Blindside is a steganography application that hides
information inside .BMP (bitmap) images. It is
a command-line utility, for which source code and
precompiled Unix binaries are available.
The Blindside homepage is located at:
http://www.blindside.co.uk/
正文
#include < stdio.h >
#include < stdlib.h >
#include < string.h >
/************************************\
* B L I N D S I D E *
* *
* Image stego/crypto tool, please *
* see http://www.blindside.co.uk *
* *
* Compile with GCC or equiv ANSI C *
* *
* John Collomosse (mapjpc@bath.ac.uk)*
* Freeware/public domain *
* *
\************************************/
#define HEAP_UN99vSIZE (102400)
#define HEAP_IN99vUN99vS (1)
#define LOOKUP_IN99vLEN (2048)
#define FALSE (0)
#define TRUE (-1)
#define PATH_SEP ('\\') /* OS Specific Path Seperator */
#define BANNER ("BlindSide BMP Cryptographic Tool - (c) John Collomosse 2000\nRelease v0.9. All Rights Reserved, contact: ma7jpc@bath.ac.uk\n\n")
#define THIS_PROTO_VER (1)
/* Heap Structure (memory storage class for uchars) */
typedef struct heapstruct {
unsigned int heapunits; /* Heap size to nearest 'unit' */
unsigned char *dataspace; /* Dataspace where data stored */
unsigned char *nextchar; /* Pointer to end of dataspace */
unsigned long heaplen; /* Length of data in heap */
} HEAP;
typedef struct lookupstruct {
unsigned long int* dataspace;
unsigned long int currentlen;
unsigned long int curitem;
} LOOKUP;
/* Bitmap Structure */
typedef struct bmpstruct {
char* signature;
long filesize;
long x_size;
long y_size;
int bitplanes;
int bpp;
long compression;
long compresssize;
long x_pix_per_metre;
long y_pix_per_metre;
long colours;
long cols_important;
HEAP* palette;
HEAP* raster;
} B99vMAP;
typedef struct pixstruct {
unsigned char red;
unsigned char green;
unsigned char blue;
} PIXEL;
/* Function prototypes */
int initialiseHeap (HEAP*);
int expandHeap (int, HEAP*);
void removeHeap (HEAP*);
int putToHeap (unsigned char,HEAP*);
int streamFileToHeap (FILE*, HEAP*);
int readBitmapFile (FILE*, B99vMAP*);
void promoteTo24 (B99vMAP*, B99vMAP*);
unsigned long resolveMaxEncode (B99vMAP*, LOOKUP*);
void writeBitmapFile (FILE*, B99vMAP*);
unsigned int biggest_of_3 (unsigned int,unsigned int,unsigned int);
void longToStream (FILE*,unsigned long int);
unsigned long streamToLong (FILE*);
void process24gotpixel (unsigned char, unsigned char*,HEAP*);
unsigned int calcEOLpad (int, long);
PIXEL getIndexedPixel (unsigned long int, B99vMAP*);
void encodeData (B99vMAP*, HEAP*, LOOKUP*);
void setIndexedPixel (unsigned long int, B99vMAP*, PIXEL);
unsigned char getNextHeapBit (unsigned long int, int, HEAP*);
int decodeData (B99vMAP*, HEAP*);
void cryptoData (HEAP* data, unsigned char* key);
unsigned char xor (unsigned char, unsigned char);
int rotl4 (int);
int hash_func (unsigned char*);
int pow (int,int);
int stricmp (const char*, const char*);
int formatDataspace (B99vMAP*, HEAP*);
void dumpFileDirectory (HEAP*);
void dumpFileStats (B99vMAP*, HEAP*);
void addFileToArchive (HEAP*, FILE*, char*);
int checkExists (char*);
int extractFile (HEAP*, char*);
void flattenBitmap (B99vMAP*, LOOKUP*);
int main (int argc, char** argv) {
int mode;
FILE* bitmap_handle=NULL;
FILE* plaintext_handle=NULL;
FILE* outfile_handle=NULL;
B99vMAP* BMPsource=NULL;
B99vMAP* BMPworking=NULL;
HEAP* filespace=NULL;
LOOKUP* hotspots;
unsigned long int i;
int isencrypted=FALSE;
char password[130];
printf(BANNER);
mode=0;
if (argc >=2) {
/* deduce mode of operation */
if (stricmp(argv ,"-A")==0)
mode=1;
if (stricmp(argv ,"-X")==0)
mode=2;
if (stricmp(argv ,"-C")==0)
mode=3;
if (stricmp(argv ,"-L")==0)
mode=4;
}
if (mode==0 || (mode==1 && (argc!=5 && argc!=6)) || (mode==2 && (argc!=3 && argc!=4 && argc!=5)) || (mode==3 && argc!=3) || (mode==4 && argc!=3)) {
printf("USAGE: BSIDE < option > < filenames - see below >\n\n");
printf("Option Description\n");
printf("~~~~~~ ~~~~~~~~~~~\n");
printf(" -A Add a file into image, need to specify files as follows\n");
printf(" BSIDE -A < BMP file > < plaintext file > < result BMP file > [password]\n\n");
printf(" -X eXtract file(s) from image, need to specify files as follows\n");
printf(" BSIDE -X < BMP file > [file to extract] [password if needed]\n\n");
printf(" -C Calculate data storage statistics of a bitmap\n");
printf(" BSIDE -C < BMP file >\n\n");
printf(" -L List files stored within a bitmap\n");
printf(" BSIDE -L < BMP file >\n\n");
printf("Please note that wildcards are NOT currently supported\n\n");
printf("BlindSide is (c) John Collomosse 2000, All Rights Reserved\nComments/suggestions to ma7jpc@bath.ac.uk, updates see www.blindside.co.uk\n");
exit(1);
}
/* Read Password off of command line */
for (i=0; i< 129; i++)
password[i]='\0';
if ((argc==6 && mode==1) || (argc==5 && mode==2)) {
isencrypted=TRUE;
for (i=0; i< 129; i++) {
password[i]=argv[6-mode][i];
if (argv[6-mode][i]=='\0')
break;
}
password[129]='\0';
}
/* Open all necessary files */
bitmap_handle=fopen(argv ,"rb");
if (mode==1)
plaintext_handle=fopen(argv ,"rb");
if (bitmap_handle==NULL) {
printf("FATAL: Could not open bitmap %s!\n",argv );
exit(2);
}
if (plaintext_handle==NULL && mode==1) {
printf("FATAL: Could not open plaintext %s!\n",argv );
exit(3);
}
/* Read source bitmap (this must be done for every command line variation) */
printf("? Reading bitmap file....");
BMPsource=(B99vMAP*)calloc(1,sizeof(B99vMAP));
BMPsource- >palette=(HEAP*)calloc(1,sizeof(HEAP));
BMPsource- >raster=(HEAP*)calloc(1,sizeof(HEAP));
initialiseHeap(BMPsource- >palette);
initialiseHeap(BMPsource- >raster);
if (!readBitmapFile(bitmap_handle,BMPsource)) {
printf("ERROR\n\nFATAL: Out of memory, while reading bitmap file\n");
exit(4);
}
printf("OK\n");
/* Analyse Bitmap */
if (stricmp("BM",BMPsource- >signature) || BMPsource- >bitplanes!=1) {
printf("FATAL: Not a valid bitmap file\n");
exit(5);
}
if (BMPsource- >compression!=0) {
printf("FATAL: BlindSide cannot work with compressed bitmaps yet\n");
exit(6);
}
if (BMPsource- >bpp==1) {
printf("FATAL: BlindSide can't work with monochrome images, as it is the colours\nwithin the image itself that are used to hide files within a bitmap.\nYou can only use bitmaps of greater colour depth (16c, 256c, 16Mc)\n");
exit(8);
}
if (BMPsource- >bpp!=4 && BMPsource- >bpp!=8 && BMPsource- >bpp!=24) {
printf("FATAL: Can't work with a bitmap with %d bits per pixel\n\nTry saving the bitmap into a different bit depth in a graphics package.\n",BMPsource- >bpp);
exit(8);
}
printf("? Image is %ld bytes (%ldx%ld), %d bits/pixel\n",BMPsource- >filesize,BMPsource- >x_size,BMPsource- >y_size,BMPsource- >bpp);
/* Colour depth increase if need be */
if (BMPsource- >bpp< 24) {
printf("? Increasing Colour Depth to 16M colours (24bpp)...");
BMPworking=(B99vMAP*)calloc(1,sizeof(B99vMAP));
if (BMPworking==NULL) {
printf("\n\nFATAL: Out of memory while increasing colour depth");
exit(4);
}
BMPworking- >palette=(HEAP*)calloc(1,sizeof(HEAP));
BMPworking- >raster=(HEAP*)calloc(1,sizeof(HEAP));
if (BMPworking- >palette==NULL || BMPworking- >raster==NULL) {
printf("\n\nFATAL: Out of memory while increasing colour depth");
exit(4);
}
if (!initialiseHeap(BMPworking- >palette) || !initialiseHeap(BMPworking- >raster)) {
printf("\n\nFATAL: Out of memory while increasing colour depth");
exit(4);
}
/* Do the promote to 24bpp */
promoteTo24(BMPsource, BMPworking);
/* cleanup source */
removeHeap(BMPsource- >palette);
removeHeap(BMPsource- >raster);
free(BMPsource);
BMPsource=NULL;
printf("OK\n");
}
else {
/* Source was fine - > already 24 bpp */
BMPworking=BMPsource;
BMPsource=NULL;
}
/* Prepare BS dataspace */
printf("? Analysing Data Patterns....");
filespace=(HEAP*)calloc(1,sizeof(HEAP));
initialiseHeap(filespace);
switch (decodeData(BMPworking,filespace)) {
case 0: printf("OK\n");
break;
case 1: removeHeap(filespace);
initialiseHeap(filespace);
if (mode==2 || mode==4) {
printf("ERROR\n\nFATAL: File does not contain any BlindSide hidden data\n");
exit(4);
}
printf("OK\n");
if (mode==1) {
printf("? Creating New Archive....");
if (formatDataspace(BMPworking, filespace))
printf("OK\n");
else {
printf("ERROR\n\nFATAL: There isn't enough space in the bitmap to hold any Blindside hidden data\n")
[8] [9] [10] [11] [12] [13]
