In some situations it is necessary to hide binary data in another file format so that it cannot be easily detected — be it to store data on image storage platforms such as Picasa, or to circumvent firewalls or mail filters. I wrote a little helper to encode byte arrays, streams or files into 24-bit bitmap images (BMP files).
Contents
1. How it works
The class methods take any kind of binary data and encode it into a 24-bit bitmap. In short, it prepends a BMP header and then simply writes the input data to the BMP file as if it were RGB image data. That means the payload is interpreted as RGB data — three bytes as one pixel.
The encodeToBitmap()-methods can be used to transform any binary data into a rectangular image and stored in the widely supported 24-bit bitmap format. The method does not hide, encrypt or compress the source data in any way. It merely prepends a bitmap header and transforms the payload as specified by the bitmap file format.
The decodeFromBitmap()-methods retrieve the orginal payload from a previously encoded bitmap. A bitmap not encoded with this class cannot be read.
Example:
Example input file /etc/motd | Encoded bitmap motd.bmp | |
Welcome to Linux Mint 12 Lisa (GNU/Linux 3.0.0-12-generic i686)
Welcome to Linux Mint 17 packages can be updated. |
||
In this example, the original input data is a text file from /etc/motd. | The output is an image file (magnified by 1900%). The original output BMP file can be downloaded here. |
2. Usage in a Java Program
Simply download the Java class and add it to your project. You can then use the following methods to encode binary data to BMP files and decode them again:
1 2 3 4 5 6 7 8 9 10 11 12 |
// Encode to 24-bit bitmap void encodeToBitmap(File srcFile, File destFile); void encodeToBitmap(byte[] srcBytes, File destFile); void encodeToBitmap(byte[] srcBytes, OutputStream destStream); void encodeToBitmap(InputStream srcStream, long srcStreamLength, OutputStream destStream); // Decode from 24-bit bitmap byte[] decodeFromBitmap(InputStream srcStream); byte[] decodeFromBitmap(File srcFile); void decodeFromBitmap(File srcFile, File destFile); void decodeFromBitmap(InputStream srcStream, OutputStream destStream); |
2.1. Example 1: Encode 3 bytes in a file
This example encodes 3 bytes into a bitmap file, and then decodes it back to a byte array.
1 2 3 4 5 |
BitmapEncoder.encodeToBitmap(new byte[] { 0x11, 0x22, 0x33 }, new File("/tmp/3-bytes.bmp")); byte[] threebytes = BitmapEncoder.decodeFromBitmap( new File("/tmp/3-bytes.bmp")); |
2.2. Example 2: Encode /etc/hosts to a gzipped bitmap
This example reads contents from the file “/etc/hosts”, and encodes it into file “/tmp/hosts.bmp.gz”. The output is gzipped before writing to the disk.
1 2 3 4 5 6 |
BitmapEncoder.encodeToBitmap( new FileInputStream(new File("/etc/hosts")), new File("/etc/hosts").length(), new GZIPOutputStream(new FileOutputStream("/tmp/hosts.bmp.gz"))); System.out.println(new String(BitmapEncoder.decodeFromBitmap( new GZIPInputStream(new FileInputStream(new File("/tmp/hosts.bmp.gz"))))); |
3. Usage from the Shell
Two of the bitmap encoding and decoding functions can be used from the command line. Only the File-based methods are implemented, not the stream-based functions.
Example:
1 2 3 4 5 6 7 |
$ java BitmapEncoder encode /etc/motd motd.bmp $ file motd.bmp motd.bmp: PC bitmap, Windows 3.x format, 9 x 8 x 24 $ java BitmapEncoder decode motd.bmp motd $ file motd motd: ASCII text |
4. Download
You can download the Java class from here:
http://blog.philippheckel.com/uploads/2013/03/BitmapEncoder.java
A few examples can be found here:
http://blog.philippheckel.com/uploads/2013/03/BitmapEncoderExamples.java
Recent Comments