I recently provided a Steganography webinar with CyberUp (@CyberUp) where I discussed what Steganography is, various methods for hiding data in files, and possible practical usage. You can watch the video here: https://youtu.be/fXMR_N-IS4s.
One of the questions I was asked was how data could be hidden by manipulating an image's dimensions (i.e. its width and height). In this blog, I'll demonstrate how this can be accomplished and what it might possibly look like in real-world application. This blog comes in two parts: a how-to and a scenario that shows how this type of steganography might be used in real-world application.
What is Steganography?
Simply put, steganography is the practice of concealing or hiding a file, message, or other data within another file. It can enable individuals to covertly communicate data and can be used to bypass content filters or Data Loss Prevention.
What are JPG (or JPEG) files?
According to the Wikipedia entry for JPEGs:
JPEG (/ˈdʒeɪpɛɡ/JAY-peg) is a commonly used method of lossy compression for digital images, particularly for those images produced by digital photography.
JPG files usually end in a .jpg or .jpeg extension and are images created using JPEG compression.
Here is what I'll be demonstrating in this blog along with some of the requirements needed if you want to follow along.
- Create a standard JPG image
- Use CyberChef or hexeditor to modify the JPG's height
- Reverse the process to reveal the hidden information
- Software to modify the image's hex values (I recommend CyberChef, but you can use hexeditor in Kali or another Linux distribution).
- Graphic software (MS Paint will work. You can also use Diagrams.net via your web browser).
Create the JPG Image
First, you'll want to create the JPG image using a graphics editor like MS Paint, Adobe Photoshop, etc. Create an image like the one below. The top of the image (indicated inside the blue dotted box) is what you want others to see. The bottom of the image (indicated inside the orange dotted box) is what you want to hide.
Edit the Image's Hex Values
This is where it gets a little tricky. Based on common JPEG markers, we need to find where the height is indicated in the JPG image. The table below shows the baseline Start of Frame (SOF0) starts at 0xFF 0xC0.
Upload the Image to CyberChef
Use CyberChef to upload your image and convert it to Hex by selecting the "To Hex" recipe.
The output gives you the hexadecimal values for the image. Hold ctrl+F in the output field and search for
ff c0. Note the following values starting at
ff c0 00 11 08 02 22 02 09
I've highlighted the relevant bytes and what they mean in the image below:
Copy the Output
Next, copy the output and click the trash icons to clear the Input and Recipe panels. In the Operations panel, enter "From Hex" and click and drag the result over to the Recipes panel.
Modify the Hex Values
Paste your hex values into the Input panel. You'll see a wand icon appear in the Output panel; click it and it will show the image represented by the input hex.
Now, in the Input panel, locate the markers identified in the previous step:
ff c0 00 11 08 02 22 02 09. It's important to know a little about base-16 numbers, but for the sake of this demo, change the height from
02 22 to
Scroll down in your Output panel and you'll see that the "[SECRET DATA HIDDEN HERE]" text is gone! It still exists in the image data, but by changing the height marker, you've told the image height to stop before that part of the image can be shown.
Save Your New Image
Save the output by clicking on the Save icon in the Output panel. The actual image has not changed - only the dimensions have changed. You can reveal the hidden content by reversing this process.
Possible Real-World Application
Cool, we know how to "hide" information by changing a JPG image's dimensions - but how could this possibly be used in the real world? I'll admit, this is not the best way to hide data, nor is it likely that this process will be used to sneak sensitive information out of a network. But, if something like this was to happen, what might it look like?
Let's walk through a scenario. In case you want to follow along, I've included the files used in this demo at the link below:
Let's assume that a company called Totally Real Company, LLC realizes that sensitive customer personally-identifiable information (PII) has been leaked. No emails have been sent outside the network that contain attached documents or links. You, a security analyst for the company, realize a very subtle change in one of their suspected employee's emails: the image they use for their signature block is larger in one email than it is in any other of their emails.
The analyst compares two files:
- signature.jpg - the image used in 99% of the employee's emails.
- signature-new.jpg - the image used in only one of the employee's emails.
Comparing the sizes of these files, you discover that the normal signature image is 16KB in size whereas the other signature image is 93KB in size. You look at the properties of both images and find a discrepancy: the original image is 546 x 181 pixels; the other image is 546 x 197 pixels.
Now, it's up to you to figure out if this employee leaked any sensitive customer data. First, you open your Kali linux VM and run
binwalk against the image to see if there are any hidden files.
binwalk -e signature-new.jpg
You get the following output:
DECIMAL HEXADECIMAL DESCRIPTION -------------------------------------------------------------------------------- 0 0x0 JPEG image data, JFIF standard 1.01 19580 0x4C7C Zip archive data, encrypted at least v2.0 to extract, compressed size: 74701, uncompressed size: 151156, name: dummy_data.csv 94453 0x170F5 End of Zip archive, footer length: 22
As you can see, there is a Zip archive hidden inside the image. The
-e option used with
binwalk extracts the hidden files and places them in a directory:
ls -l in the
_signature-new.jpg.extracted folder and find the following files:
You see two files were extracted: 4C7C.zip and dummy_data.csv. The CSV file is empty, so you try to unzip the Zip file, but it asks you for a password:
Archive: 4C7C.zip [4C7C.zip] dummy_data.csv password:
Let's see if that image contains the password hidden somewhere. Remember, the dimensions of the original image and the new image changed. Maybe if you mess with the height marker of the new, larger image, it will reveal its secret.
Load the signature-new.jpg file into CyberChef and copy its output.
Clear the panels and paste the output into the Input panel. Choose the From Hex recipe and click on the wand icon on the Output panel to render the image.
Change the height marker from
00 c5 to
00 dd. The image will reveal the password below the signature block!
It looks like Whitney here is sending client data to someone on the outside who knows just how to unlock the hidden data. Now, unzip the Zip file using the password you've discovered.
Unzipping the file, we see the customer data in CSV format:
id,first_name,last_name,email,gender,ip_address,street,city,state,username,passwd,phone,card_numid,first_name,last_name,email,gender,ip_address,street,city,state,username,passwd,phone,card_num 1,Jenelle,Wakefield,firstname.lastname@example.org,Female,184.108.40.206,4 Prairie Rose Lane,San Diego,California,jwakefield0,RhdtWsL,619-992-1803,3575770055669581 2,Cam,Hanson,email@example.com,Male,220.127.116.11,7 Alpine Drive,Phoenix,Arizona,chanson1,DSZR2aBUl,602-405-5244,4041593411071985 3,Jody,Heeps,firstname.lastname@example.org,Female,18.104.22.168,9145 Cordelia Road,Corpus Christi,Texas,jheeps2,gpM7HetENP39,361-963-6874,3586855264682470 ...
It's unlikely that sensitive data will be leaked using this method, but it highlights a blind spot in some security applications and practices: most security applications don't do a very good job when it comes to identifying steganography. Some applications might pick up on the extra Zip header in the JPG file, but if the individual encrypted the Zip file itself rather than just its contents, then it would be very difficult to detect.