📜 ⬆️ ⬇️

LSB steganography

Once upon a time I wrote my first post on Habré . And that post was devoted to a very interesting problem, namely steganography. Of course, the solution proposed in that old topic cannot be called steganography in the true sense of the word. This is just a game with file formats, but, nevertheless, quite an interesting game.

Today we will try to dig a little deeper and consider the LSB algorithm. If you're interested, you are welcome under the cat. (Under the cut traffic: about a megabyte.)

First of all, you need to make a small introduction. Everyone knows that the purpose of cryptography is to make it impossible to read secret information. Of course, cryptography has its own uses, but there is another approach to data protection. You can not encrypt information, but to pretend that we do not have it. This is what steganography is invented for. Wikipedia assures us that, “steganography (from the Greek. Στεγανοσ - hidden and Greek. Γραφω - I write, literally“ secret writing ”) - is the science of the hidden transfer of information by keeping in secret the very fact of transmission.

Of course, no one forbids combining cryptographic and steganographic methods. Moreover, in practice they do this, but our task is to understand the basics. If you carefully study the article from Wikipedia, you can learn that the so-called steganography algorithms appear. container and message. A container is any information that helps to hide our secret message.
')
In our case, the container will be a picture in BMP format. To begin, consider the structure of this file. The file can be divided into 4 parts: the file header, image header, palette, and the image itself. For our purposes, you need to know only what is written in the title.

The first two bytes of the header are the BM signature, then the double word contains the file size in bytes, the next 4 bytes are reserved and must contain zeros, and finally, another double word contains the offset from the beginning of the file to the image bytes. In a 24-bit bmp file, each pixel is encoded with three bytes of BGR.

Now we know how to get to the image, it remains to understand how we can write down the information we need. For this we need the LSB method. The essence of the method is as follows: we replace the low-order bits in bytes responsible for color coding. Suppose if the next byte of our secret message is 11001011, and the bytes in the image are ... 11101100 01001110 01111100 0101100111 ..., then the encoding will look like this. We will break the secret message byte into 4 two-bit parts: 11, 00, 10, 11, and replace with the received fragments the lower bits of the image: ... 111011 11 010011 0 0 011111 1 0 0101100111 .... Such a replacement is generally not noticeable to the human eye. Moreover, many old output devices will not even be able to display such minor changes.

It is clear that it is possible to change not only 2 low bits, but also any number of them. Here is the following pattern: the more bits we change, the more information we can hide, and the more noise in the original image it will cause. For example, here are two images:

image
image

With all my desire, I was never able to see the differences between them, and nevertheless, in the second image, using the described method, the poem “Snark Hunt” by Lewis Carroll was hidden. If you have read this far, then you will certainly be interested in learning about the implementation. She is pretty simple, but I will immediately warn you that everything has been done in Delphi. There are two reasons for this: 1. I consider Delphi to be a good language; 2. This program was born, in the process of preparing a course on the basics of machine vision, and the guys with whom I read this course, so far nothing but Delphi know. For those who are not familiar with the syntax, one thing should be clarified: shl x - bitwise left shift by x, shr x - bitwise right shift by x.

We consider that we write the text stored in the string into the container and replace the lower two bytes:
Code to write:

for i : = 1 to length ( str ) do
begin
l1 : = byte ( str [ i ] ) shr 6 ;
l2 : = byte ( str [ i ] ) shl 2 ; l2 : = l2 shr 6 ;
l3 : = byte ( str [ i ] ) shl 4 ; l3 : = l3 shr 6 ;
l4 : = byte ( str [ i ] ) shl 6 ; l4 : = l4 shr 6 ;

f . ReadBuffer ( tmp , 1 ) ;
f . Position : = f . Position - 1 ;
tmp : = ( ( tmp shr 2 ) shl 2 ) + l1 ;
f . WriteBuffer ( tmp , 1 ) ;

f . ReadBuffer ( tmp , 1 ) ;
f . Position : = f . Position - 1 ;
tmp : = ( ( tmp shr 2 ) shl 2 ) + l2 ;
f . WriteBuffer ( tmp , 1 ) ;

f . ReadBuffer ( tmp , 1 ) ;
f . Position : = f . Position - 1 ;
tmp : = ( ( tmp shr 2 ) shl 2 ) + l3 ;
f . WriteBuffer ( tmp , 1 ) ;

f . ReadBuffer ( tmp , 1 ) ;
f . Position : = f . Position - 1 ;
tmp : = ( ( tmp shr 2 ) shl 2 ) + l4 ;
f . WriteBuffer ( tmp , 1 ) ;

end ;

read code:
for i : = 1 to MsgSize do
begin
f . ReadBuffer ( tmp , 1 ) ;
l1 : = tmp shl 6 ;
f . ReadBuffer ( tmp , 1 ) ;
l2 : = tmp shl 6 ; l2 : = l2 shr 2 ;
f . ReadBuffer ( tmp , 1 ) ;
l3 : = tmp shl 6 ; l3 : = l3 shr 4 ;
f . ReadBuffer ( tmp , 1 ) ;
l4 : = tmp shl 6 ; l4 : = l4 shr 6 ;
str : = str + char ( l1 + l2 + l3 + l4 ) ;
end ;


Well, for the very lazy - a link to the program and its source code .

Thank.

Source: https://habr.com/ru/post/112976/


All Articles