Steganography

 

#include <stdio.h>
struct
{
char a[6];
short width,height;
unsigned char flags;
unsigned char backindex;
unsigned char pixelaspectratio;
}gif;
FILE *fp;
int size;
main(int argc,char *argv[])
{
fp=fopen(argv[1],"rb");
fread(&gif,sizeof(gif),1,fp);
printf("%c%c%c%c%c%c\n",gif.a[0],gif.a[1],gif.a[2],gif.a[3],gif.a[4],gif.a[5]);
printf("Width=%u Height=%d\n",gif.width,gif.height);
printf("Color table present %d\n", gif.flags & 0x80);
printf("Number of colors %d\n",((gif.flags & 0x70) >> 4) + 1);
printf("sort Flag %d\n",gif.flags & 0x08);
size = (gif.flags & 0x07) + 1;
size = 1 << size;
printf("Size of color table %d\n",size);
printf("Background Color Index %d\n",gif.backindex);
printf("Pixel Aspect Ratio %d\n",gif.pixelaspectratio);
}
 
GIF89a
Width=538 Height=567
Color table present 128
Number of colors 8
sort Flag 0
Size of color table 256
Background Color Index 255
Pixel Aspect Ratio 0

A gif file starts with a header and then follows the actual file data. We create a structure gif that maps the fields of the gif file format. We open the file name specified as a command line argument. We use the fread function to read the first 13 bytes into this structure. We then display the members of this structure. This data starts with a 6 byte signature.

The first 3 bytes is the signature which are the characters GIF and the next 3 bytes are he version number which is either 87a or 89a. The 87a actually stands for May 87 and 89a for July 89. This means that we have effectively two versions of the gif file format. This signature is followed by two shorts which are the width and height of the picture in pixels.

This is the size of the area that the gif file wants on the device it is to be drawn or rendered. These numbers are logical device numbers as they could refer to your monitor or a printer. Now we have a flags field that represents four different values as.

Global Color Table Flag 1 Bit
Color Resolution 3 Bits
Sort Flag 1 Bit
Size of Global Color Table    3 Bits

The high bit tells us if there is a global color table present or not. We simply bit wise and with 0x80 and if the number is 128, we have the high bit as 1 or a color table is present. Normally most gifs we have seen have a global color table. This global color table immediately follows the 13 byte header.

The next three bits  i.e. 4, 5 and 6 will contain the color resolution. All color is made up of the three primary colors red, green and blue. The question is how much of these three colors are we allowed to use. The value in this field plus 1 is the number of bits per color. The maximum value is 8 as we then get a value 0 – 255 of each color. If we have 4 bit color resolution then we are allowed a range of 0 - 15 for each color.

To get at the value from the packed field we first bit wise and with 70 and then right shift by 4 to get bytes 4,5 and 6 to the first three bytes. We then add 1 to get the actual color resolution. Three bits can only gives us a color resolution of 7 and we use 8 bit color normally.

The 4th is called the sort flag and tells us whether the color table is sorted or unsorted. Sorting a color table is not on color but on increasing use of that color. Thus colors used more, we place them first. This is used by decoders who can display only a few colors to know which are the most widely used colors. Most of the time we do not have a sorted color table.

The first three bits are the size of the global color table. To get the actual value, we first add one to this value and then we take 2 and raise it to this value. In the program we left shift by that number as left shifting is equivalent to  multiplication. Normally the size of the global color table is fixed to 256 colors.

The gif file has a real limitation of 256 on the number of colors a single file can use This is why the size of  the global color table is 256 even though it may not use up that many colors.

The next char is the background color to be used for the picture. In our case the value is 255. A background color is used whenever a pixel has no foreground color. For those pixels the color at color table index of 255 will be used.

 

The last char is 0 which denotes the aspect ratio of the pixel in the image. Now we have a 768 byte table called the global color table. This table is made of up a 256 3 bytes values. Each three byte value represents a red, green and blue ranging from 0 to 255.

After the color table we have the actual data of the gif table. This is simply a series of numbers from 0 to 255 specifying which color the pixel should be drawn in. It is this table of color numbers that is compressed using the LZW compression scheme.

The gif specs have a lot of other sections which we will not go into at this moment.

#include <stdio.h>
FILE *fp;
unsigned char a[768],b[768],*p = "Vijay Mukhi & Sonal";
int cnt=0,i,cnt1,len;
main(int argc,char *argv[])
{
fp = fopen(argv[1],"r+b");
fseek(fp,13,0);
fread(a,768,1,fp);
len = strlen(p);
cnt1=0;
while (cnt1 <= len )
{
for ( i=0; i<8; i++)
{
int bit = ((*p & (128 >> i)) != 0) ? 1 : 0 ;
b[cnt] = bit;
cnt++;
}
cnt1++;
p++;
}
for (i=0;i < cnt; i++)
{
printf("cnt=%d b[i]=%d %d",cnt,b[i],a[i]);
if ( b[i] == 1)
a[i] = a[i] | 1;
else
a[i] = a[i] & 0xfe;
printf(" %d\n",a[i]);
}
fseek(fp,13,0);
fwrite(a,768,1,fp);
fclose(fp);
}

The next two programs need to be run together. The above program stores the contents of a  string p into the gif file. It stores it in such a way that it is nearly impossible to find out the existence of such a string. The letter A is ASCII 65 and is stored as a series of bits 01000001.

All that we do is take each of the above bits and place them as the first bit of each color bytes. Thus the first bit of the color red will be 1, the first bit of color green will be 0, the first bit of the color blue will be 0. We then take the next three bits 000 and place them as the first bits of the second color.

This way we can store 768 bits of information as our color table is made up of 256 entries. Dividing 768 by 8 gives us 98 bytes of information. The first bit of any byte has a multiple of 1 and even though we change it, the change in the final byte value will either be the same or the value will increase or decrease by only 1.

Such a small change of color cannot be seen by the naked eye. This is the power of stenography, it lets us place stuff in files in such a way that nobody can find out. In the case of a gif file we cannot change the header or the actual pixel colors as the eye will realize some change. Thus change the first bit of the color table, the colors will change but will not be noticeable.

Like the previous program, we pass the gif file name as a parameter. We then use the fseek function to skip the header that makes up 13 bytes. The parameters of the fseek function are file handle, number of bytes to move and finally 0 stands for from the beginning of the file, 1 from where we are and 2 from the end.

The file pointer is at byte 14 which is the start of the color table. We use the fread function to read the entire color table into a array a. The four parameters of the  fread function are the memory where we want the data to be read, the second and third are the number of bytes to be read, we multiply them to get at this number and the last is file handle.

The len variable is the length of the string we want to write to the gif file. We use the cnt1 variable to loop though the while. Its value starts  at 0 and then increases by 1 each time and we quit out of the while when its value reaches the value of len.  One byte is made up of 8 bits and hence we have a for loop that goes on 8 times with the value of I ranging from 0 to 7.

The value of *p will be the char or byte p is pointing to. We need to pick up one bit at a time. When I is 0 at the start of the loop, we are bitwise anding *p with 128. This simply gives us only the high bit  and the rest of the bits are 0. If this number is larger than 0, the ternary operator is true and returns 1.

If the high bit is 0, we are left with 0, which gives us 0 or false. A right shift is dividing by 2. The second time in the for loop gives I a value of 1, 128>>1 gives us 64. We are now checking the second last bit as we are bitwise anding with 64. This is how we are extracting a bit at a time from every char that makes up our string.

 

We store the bit in the array b using cnt as the index to this array. We also increase cnt by 1 in the for loop. The array b will contain a 0 or 1 depending upon the value of each bit of our string. At the end of the while loop we increase cnt1 and p. Now that we have an array of bits in b, we need to write out these values in the array a.

We use a for loop looping with I from 0 to cnt. If the member of b using I as the index is 1, we simply bit wise or the corresponding color member in the array a with 1. If not, it could only mean that the bit is 0, so we need to set the first bit of the array a member at index I to 0. Setting a bit to 0, means bit wise anding it with a 0, so we use 0xfe.

We use the fseek function to move to the 13 byte and use fwrite to write the changed array a over the existing color table on disk. This is how we hide our string in the gif file.

#include <stdio.h>
FILE *fp;unsigned char a[768],b[768],c[100];
int i,tot,bit,cnt,cnt1;
main(int argc,char *argv[])
{
fp = fopen(argv[1],"r+b");
fseek(fp,13,0);
fread(a,768,1,fp);
cnt1 = 0;
while (1)
{
tot = 0;
for( i = 0; i < 8 ; i++)
{
bit = a[cnt1+i] & 1;
tot += (bit << (7-i));
printf("bit=%d tot=%d\n",bit,tot);
}
c[cnt] = tot;
if ( c[cnt] == 0)
break;
cnt++;
cnt1 =  cnt1 + 8;
}
printf("%s\n",c);
}

We now use the third program to read the string stored by the earlier program. We open the same gif file now for reading, r+ allows us to read and write to the file. We seek to the start of the color table and read the entire color table of 768 bytes in a array a.

We set the cnt1 variable to 0 and enter a indefinite while loop as we do not know how large the message stored is. We will use the tot variable to store the count of the byte which is stored as individual bits. We enter a for loop which takes I form 0 to 7 for a total of 8 times.

We use the cnt1 and I variable to let us read one byte at a time. At the end of the outer while loop we will increase cnt1 by 8 and I increases by 1 each time due to the for loop.  The value of a[] will be an entire byte but as bit wise and with a 1, we will have with us only the first bit.

We then left shift this bit that many times to the left so that it occupies its rightful place. The first bit should be shifted by 7 so that it occupies the last high bit. As the value of I increases by 1, the first bit is left shifted by 7, the second by 6 and the third by 5 and so on. The last bit is not shifted at all. This is how tot gets its final value by using  one bit at a time.

We could have used bit wise oring instead of shifting. We use the array c to store the byte value in tot and if the value of tot is 0, we have reached the end of the string. When this happens we quit out of the outer while loop. When we are out we display the string stored in array c.

The only problem in the above program is the limitation of the size of the string that can be used. Also we can encrypt the string before we store it.

We will now add our string to a wav file using the same method used for gif files. The advantage with a wav file is that we have lots of space unlike a gif file.

#include <stdio.h>
FILE *fp;
char c[4];int i,where,len,cnt1,cnt;long size;char a[1000],b[1000];
char *p = "Vijay Mukhi & Sonal and the whole world";
main()
{
fp = fopen("z.wav","r+b");
while (1)
{
fread(c,4,1,fp);
i = strncmp(c,"data",4);
if ( i == 0)
break;
fseek(fp,-3,1);
}
len = strlen(p);
cnt1=0;
fread(&size,4,1,fp);
where = ftell(fp);
fread(a,768,1,fp);
len = strlen(p);
cnt1=0;
while (cnt1 <= len )
{
for ( i=0; i<8; i++)
{
int bit = ((*p & (128 >> i)) != 0) ? 1 : 0 ;
b[cnt] = bit;
cnt++;
}
cnt1++;
p++;
}
for (i=0;i < cnt; i++)
{
if ( b[i] == 1)
a[i] = a[i] | 1;
else
a[i] = a[i] & 0xfe;
}
fseek(fp,where,0);
fwrite(a,768,1,fp);
fclose(fp);
}

Most of the above program remains the same. A wav file starts with the signature RIFF followed by a chunk size and then another two signatures WAVE and fmt . This could only mean that a wav file is made up of a series of structures which begin with 4 bytes of signature.

It is these structures that tell the wav file player what the sample size is and how  the duration of the wav file. The most important structure has a signature data followed by a long that tells us how much data follows. Our job is thus to find the string data in the wav file. We start with an indefinite while loop and read the first four bytes. We strncmp these 4 bytes with the chars data.

If we meet a match, the function returns 0 and we quit out by the break. If we do not we use the fseek function to move back 3 bytes and then read bytes 2, 3 4 and 5 and the process caries on. Normally these structures begin at 4 byte boundaries but hey why take a chance. When we get out of the loop we read a long that is the size of the wav data using fread.

We are now positioned at the actual image data. We use the where variable to store when we are in the file, a value returned by the ftell function. Then we do whatever we did in the earlier code. At the end, we use the fseek function to move back to the start of the wav data using the where variable.

#include <stdio.h>
FILE *fp;unsigned char a[768],b[768],c[100];
int i,tot,bit,cnt,cnt1;
main(int argc,char *argv[])
{
fp = fopen("z.wav","r+b");
while (1)
{
fread(c,4,1,fp);
i = strncmp(c,"data",4);
if ( i == 0)
break;
fseek(fp,-3,1);
}
fseek(fp,4,1);
fread(a,768,1,fp);
cnt1 = 0;
while (1)
{
tot = 0;
for( i = 0; i < 8 ; i++)
{
bit = a[cnt1+i] & 1;
tot += (bit << (7-i));
}
c[cnt] = tot;
if ( c[cnt] == 0)
break;
cnt++;
cnt1 =  cnt1 + 8;
}
printf("%s\n",c);
}

The program to retrieve the string is easier as we simply move to the data structure like we did before and then keep reading the first bit of each byte.

Back to the main page