/* bmplsb.c Extracts the LSBs of a 24 bit color bitmap image and creates a new image based on the selected bit value. N. DeBaggis for The Honeynet SOTM 26, Feb. 2003. usage: bmplsb [in-bitmap] [out-bitmap] [bit 0 - 7] Where in-bitmap is a 24 bit color bitmap image. This converts each color byte into either 0x00 or 0xff dependant on the selected bit value of the color byte, writes the new enhanced bitmap to the file out-bitmap. Example: the color data for pixel x = RGB = 0x103380 so the new pixel will be: RGB = 0x00ff00 if you select bit 0. What we are looking for in the resultant image is a random looking block of colors. Using Invisible Secrets to stego a file into a bmp will show this discrepancy clearly. Linux compile: Compile with gcc using the -fpack-struct flag so the bmp header struct can be read in one shot from the bmp file. Windows compile: Make a new project workspace in VC++ and add both the bmplsb.c and bmp.h files to it. Change the struct alignment in the Project Options - C/C++ - code generation section so you are aligning on 1 byte bounds. */ #include #include #include #include "bmp.h" #define BCOLORBITS 24 FILE *in, *out; bmpinfo bmp; int bit = 1; void usage(void){ printf("Usage: bmplsb [inbmp] [outbmp] [bit 0 - 7]\n"); } void printinfo(bmpinfo *bmp, char *inf, int bitn, char *outf){ fprintf(stderr, "----------------------------------------\n"); fprintf(stderr, "Bitmap info:\n"); fprintf(stderr, "----------------------------------------\n"); fprintf(stderr, "file size: %u\n", bmp->biFileSize); fprintf(stderr, "bmp image size: %u\n", bmp->biSizeImage); fprintf(stderr, "data offset: %u\n", bmp->biDataOffset); fprintf(stderr, "bmp width: %u\n", bmp->biWidth); fprintf(stderr, "bmp height: %u\n", bmp->biHeight); fprintf(stderr, "bmp bit count: %u\n", bmp->biBitCount); fprintf(stderr, "max hide bytes: %u\n\n", (dword)(bmp->biSizeImage/8)); fprintf(stderr, "Creating bit enhanced image using bit #%u\n" "of file %s into file %s\n", bitn, inf, outf); } int getbits(FILE *in, FILE *out){ byte buf = 0; byte result = 0; while(fread(&buf, sizeof(buf), 1, in)){ result = (buf & bit) ? 0xff : 0x00; fwrite(&result, sizeof(result), 1, out); } return 0; } int main(int argc, char *argv[]){ int tbit = -1; if(argc != 4){ usage(); exit(1); } tbit = atoi(argv[3]); if(tbit < 0 || tbit > 7){ fprintf(stderr, "bit must be in the range 0 to 7\n"); exit(1); } bit <<= tbit; if((in = fopen(argv[1], "rb")) == NULL){ fprintf(stderr, "Error opening input bmp file %s, exiting\n", argv[1]); exit(1); } if((out = fopen(argv[2], "wb")) == NULL){ fprintf(stderr, "Error opening output bmp file %s, exiting\n", argv[2]); fclose(in); exit(1); } if(fread(&bmp, sizeof(bmp), 1, in) != 1){ fprintf(stderr, "Error reading bmp header, exiting\n"); fclose(in); fclose(out); exit(1); } if(bmp.biType != BMAGIC){ fprintf(stderr, "Not a bitmap file, exiting\n"); exit(1); } if(bmp.biBitCount != BCOLORBITS){ fprintf(stderr, "Bitmap file is not 24 bit color, exiting\n"); exit(1); } fwrite(&bmp, sizeof(bmp), 1, out); fseek(in, bmp.biDataOffset, SEEK_SET); if(getbits(in, out)) fprintf(stderr, "error reading input file %s\n", argv[1]); fclose(in); fclose(out); printinfo(&bmp, argv[1], tbit, argv[2]); return 0; }