I have developed a small Java program to perform Chi-Square attack and LSB Enhancement attack on 24-bit BMP images.
What does LSB Enhancement mean?
Well, it is the process of manipulating the least-significant-bit(LSB) of image data in order to produce an output to discover the embedded data.
Well, it is the process of manipulating the least-significant-bit(LSB) of image data in order to produce an output to discover the embedded data.
How it works?
First of all we need to read the image data in Java. I used an already implemented Java class which was based on the code from authors Abdul Bezrati and Pepijn Van Eeckhoudt. The class is called BitmapLoader and it can read both 8-bit and 24-bit BMP images. The method loadBitmap(String file) returns a BufferedImage of type BufferedImage.TYPE_4BYTE_ABGR which means that when a pixel value is read using image.getRGB(x, y) it will return a 32-bit integer value of which the left most 8 bits will represent the ALPHA component, next 8 bits BLUE component, next 8 bits GREEN component and the least significant 8 bits will represent the RED component of the pixel. We can read these components individually by performing bitwise shift operations on the RGB value as
First of all we need to read the image data in Java. I used an already implemented Java class which was based on the code from authors Abdul Bezrati and Pepijn Van Eeckhoudt. The class is called BitmapLoader and it can read both 8-bit and 24-bit BMP images. The method loadBitmap(String file) returns a BufferedImage of type BufferedImage.TYPE_4BYTE_ABGR which means that when a pixel value is read using image.getRGB(x, y) it will return a 32-bit integer value of which the left most 8 bits will represent the ALPHA component, next 8 bits BLUE component, next 8 bits GREEN component and the least significant 8 bits will represent the RED component of the pixel. We can read these components individually by performing bitwise shift operations on the RGB value as
int pRGB = image.getRGB(x, y);
int alpha = (pRGB >> 24) & 0xFF;
int blue = (pRGB >> 16) & 0xFF;
int green = (pRGB >> 8) & 0xFF;
int red = pRGB & 0xFF;
LSB enhancement means setting the component value to 255 if the least-significant-bit is 1 or leave as it is if 0. As a result of this operation, the image will have some flashy colours in the parts where the LSBs were 1s.
How it works in java? First we need to set the alpha component to 255 or the background of the image will be transparent. Then we need to check the red, green and blue components if the LSBs are 1, if they are, we will set these values to 255. It is performed with the following lines of code in Java:
int pRGB = 255 << 24; //set the alpha component
int temp = 0;
if ((red & 0x01) == 1) {//check if the LSB is 1
pRGB += 255;
}
if ((green & 0x01) == 1) {//check if the LSB is 1
temp = pRGB;
pRGB = 255 << 8;
pRGB += temp;
}
if ((blue & 0x01) == 1) {//check if the LSB is 1
temp = pRGB;
pRGB = 255 << 16;
pRGB += temp;
}
lsbImage.setRGB(x, y, pRGB);//set the RGB value of the image.
When the above operation is performed on all pixels of the image, the resulting lsbImage which is of type BufferedImage will reveal the parts of the image with the hidden data.
How Chi-Square attack works?
This attack was developed by Andreas Westfeld and Andreas Pfitzmann in 2000 (Andreas Westfeld and Andreas Pfitzmann, Attacks on Steganographic Systems. Breaking the Steganographic Utilities EzStego, Jsteg,Steganos, and S-Toolsand Some Lessons Learned, 2000).
First of all, we need to know what is Chi-Square analysis? It is a statistical test to measure if a given set of observed data and an expected set of data are similar or not. This is the main idea, you can read about it in more details in any statistics book.
The idea of this attack is to compare Pair-of-Values' observed frequencies with their expected frequencies and calculate p value which will represent the probability of having some embedded data in an image.
What do we mean by Pair-of-Values? According to Westfeld & Pfitzmann, when some data like encrypted text is embedded into an image the LSB values of the original data change in a way that the number of these pairs become nearly equal while they differ so much when there is no embedding. We can see pairs of values as the following bit sequences in our case where we have 8-bit components. As a result we have 128 pairs of values like 0-1, 2-3, 4-5, ..., 254-255. What we do with these values? We will count the occurrences of the individual colour values in the image and we will come up with the observed frequencies data set which will be used in the chi-square test. But we also need an expected data set which is explained by Westfeld & Pfitzmann as the average of the occurrences of the values in a pair.
00000000
00000001
00000010
00000011
00000100
00000101
........
11111110
11111111
For the observed data set we just need to take the frequency of one of the pairs. It will not make any difference because the expected value is the average of both values in a pair which means that both of the values are in the same distance to the average. For example, we counted 800 occurrences for value 0 and 200 occurrences for value 1. The expected value will be the average of these two values which will result in 500. Both of the observed values are at the same distance to the average which is 300.
How is it implemented in Java?
I have a class named PoV which has only the following attribute
I have a class named PoV which has only the following attribute
private long[] pov = new long[256];
and three methods as
public double[] getExpected() { double[] result = new double[pov.length / 2];
for (int i = 0; i < result.length; i++) {
double avg = (pov[2 * i] + pov[2 * i + 1]) / 2;
result[i] = avg;
}
return result;
}
public void incPov(int i) {
pov[i]++;
}
public long[] getPov() {
long[] result = new long[pov.length / 2];
for (int i = 0; i < result.length; i++) {
result[i] = pov[2 * i + 1];
}
return result;
How do we perform the Chi-square test on the image?
The performed test is the iterated version of the above described attack and it is performed after reading a predefined amount of data(chunk size) is read. I chose chunk-size as 128 bytes which means after reading 128 bytes of image data, a test is performed and its result is stored. The total number of tests/chunks in the image is
numOfChunks=(int)(Math.floor((width*height*3)/chunkSize)+1);
which will also be the width in pixels of the output generated at the end. Sample outputs of the program are given below.
Download available at: https://sourceforge.net/projects/chi-square/
for (int i = 0; i < result.length; i++) {
double avg = (pov[2 * i] + pov[2 * i + 1]) / 2;
result[i] = avg;
}
return result;
}
public void incPov(int i) {
pov[i]++;
}
public long[] getPov() {
long[] result = new long[pov.length / 2];
for (int i = 0; i < result.length; i++) {
result[i] = pov[2 * i + 1];
}
return result;
How do we perform the Chi-square test on the image?
The performed test is the iterated version of the above described attack and it is performed after reading a predefined amount of data(chunk size) is read. I chose chunk-size as 128 bytes which means after reading 128 bytes of image data, a test is performed and its result is stored. The total number of tests/chunks in the image is
numOfChunks=(int)(Math.floor((width*height*3)/chunkSize)+1);
which will also be the width in pixels of the output generated at the end. Sample outputs of the program are given below.
![]() |
| 480x360 embedded with 6 KB data |
![]() |
| LSB Enhancement output |
![]() |
| Chi-square attack output |
Download available at: https://sourceforge.net/projects/chi-square/



I think the explanation is still missing a bit but still it is something to share.
ReplyDeleteshould i perform this on graylevel pixel matrix ???
ReplyDeleteYou can perform the chi-square test on 8-bit grayscale pixels but the implementation should be different than the one given above. Above implementation is a specific case for 24-bit RGB bitmap images only.
Deletehi
Deleteany one has the Matlab code for chi square attack in 8 bit gray scale?
Hello Parisa,
Deletesorry for such a late reply and also I don't have any interest in Matlab but I am sure it is much easier to perform these operations on arrays in Matlab.
Hi
DeleteThis is Matlab Code. Chi-Square Attack
https://www.dropbox.com/s/o83yfxy2rr80b67/stego_works01.rar
hello
Deletethis zip folder contain a lot of matlab file which file is related to chi-square attack. Plaese help me to find it out
I can't open the shared file on the dropbox
DeleteDid anybody found a matlab code for implementing chi attack on image?
DeleteCan you mention a way to possibly reverse this process? I have a similar steganographied image using LSB insertion.
ReplyDeleteHello,
DeleteIn case of an image with LSB enhancement applied, I cannot think of a way to reverse it back to its original state because there is no clue about the original values of RGBs. They are set to either 255 or 0 depending on their Least Significant Bit.
Hi
ReplyDeleteI am working on a steganography technique and in dire need of a good steganalysis program for testing purpose. I am working on JPEG images and mainly on grayscale images. Unfortunately, I don't have time to understand and implement Chi Square Attack and hence, would like to request for your help. Can you please help in this regard? Thanks.
Hi, I am sorry but I cannot help with this. This was a project that I did during my studies, if you wish, you can reuse my code and adapt it for the use of jpeg images (https://sourceforge.net/projects/chi-square/).
DeleteHey there,
ReplyDeletecan you please tell me how to calculate probability of detection based on chi square score?? Thanks
Hello Jay,
DeleteYou can search for the literature I mentioned in the article and find out the details about the probability and so on.
(Andreas Westfeld and Andreas Pfitzmann, Attacks on Steganographic Systems. Breaking the Steganographic Utilities EzStego, Jsteg,Steganos, and S-Toolsand Some Lessons Learned, 2000)
Hye there, I am using this tool to detect whether is there is any embedded message in a picture. When I run the tool using original picture, it shows like the example above. But, when I run it using the picture with message hidden in it, it only produces black output, nothing grayscale. Please help me enlighten the output I get. Thanks.
ReplyDeleteHello,
DeleteI am sorry but I cannot really provide any support on this, use it as is.
Cheers
Thank you in advance
ReplyDeleteHello,
ReplyDeleteis it possible on video files
No it is not, this solution works only on images
DeleteNo it is not, this solution works only on images
Delete