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