48 comments

[ 3.0 ms ] story [ 110 ms ] thread
Hmm.

So combined with Apple's CSAM scanner, you can put CSAM inside a cat photo... And then anonymously leak the cat photo and tool to show it's CSAM. And then the CSAM scanner will flag the hash and alert the police of the user.

And the target victim would never know.

This is substantially more complicated than finding a collision against the perceptual/“content aware” hash that Apple was planning on using.
“A picture of you, holding a picture of me, in the pocket of my blue jeans.”
Ages ago I made a tool that does a similar method (rewrite the least-significant N bits of a pixel in the cover image with the most-significant N bits of the corresponding pixel of the hidden image). In my tool N is configurable.

The main pitfall is that it doesn't work very well if the output is saved as a JPEG because of the compression.

I think OP's idea of encoding all of the bits of the hidden image, by using a cover image with more pixels, is a good improvement: you get no loss of quality in the hidden image, and you vastly reduce the loss of quality in the cover image.

https://incoherency.co.uk/image-steganography/

Steganography is a very exciting topic and is not limited to image data but can also be applied to, e.g., audio data.

I’ve done something similar in the past and embedded Merkle tree nodes in an image to allow partial integrity validation. It was a fun little project:

https://github.com/dennis-tra/image-stego

In the original MIPS-32 instruction set, some fields in the instruction are unused in certain instructions. (The shift field in R-format instructions is an example.) I had a student who did a project to take real MIPS machine language programs and store textual data in them by repurposing these unused fields.
Videos provide much more space to hide data in than your typical images do.

I've always wondered if there was some way that hidden information inside videos could be designed to survive the re-encoding that youtube does when you upload a video.

Has anyone investigated this?

Did you read the story of 2011's storming of Bin Laden compound? And that they found heaps of porn videos? And that's how he exchanged messages with his network by using different open porn sites where they uploaded porn? I recommend reading it, it's quite interesting.

Where is the link? Well, I don't give 100%, I like to only point people in the right direction, rest is left as an exercise for the reader.

Yes, the keyword you are looking for is "watermark"
An expedient way to hide another photo (or any data) in another photo is to simply append it to the original photo. It's certainly not as secure as OP's method, but it has the advantage of not requiring any third party app, just standard command line tools.

Example: you have duck.jpg (21500 bytes) and you want to hide flower.jpg (37733 bytes). Do this to create a larger file (59233 bytes):

  cat duck.jpeg flower.jpeg > bigger-duck-file.jpg
Anyone looking at bigger-duck-file.jpg will see the duck. Every image viewing program I tried displays the duck and none of them complain about the extra bytes (the hidden image) at the end of the file.

The recipient can extract the hidden file as follows:

  tail -c 37733  bigger-duck-file.jpg > flower.jpg
You would have to tell the recipient the size of the hidden file by some other means. But there might be a simple command-line way to determine where the image data for duck.jpg really ends in the bigger file, so maybe you wouldn't need that step.
And as someone else has probably said, if the second file is a zip file.. the file will open successfully in most zip programs without any modification.
That doesn't make sense to me. Zip was designed so it could be written to a non-seekable stream, meaning the Central Directory structure that points to all of the file records is at the end of the archive. Its location is found at the very end of the archive in the End Of Central Directory record. Problem is that it's a pointer to the offset of the Central Directory relative to the beginning of the archive, and so are the pointers to the file records in the directory.

So, if you just append a ZIP file to another file, it will screw up all the internal pointers in the ZIP file. If you overlay a file on the beginning of the ZIP, most of it should be recoverable, though.

Another clever hack is that you can put a batch file in the beginning of the ZIP with the compression level set to "none", rename it to .CMD or .BAT, and run it like a batch file. If said batch file locates and unzips itself, you've got a self-extracting archive.

Yeah, I don't quite know the details of how it works. Just that it does

  $ file some.*
  some.jpg: JPEG image data, JFIF standard 1.02, aspect ratio, density 1x1, segment length 16, baseline, precision 8, 64x736, components 1
  some.zip: Zip archive data, at least v1.0 to extract
  $ cat some.* > new.jpg
  $ file new.jpg
  new.jpg: JPEG image data, JFIF standard 1.02, aspect ratio, density 1x1, segment   length 16, baseline, precision 8, 64x736, components 1
  $ unzip -l new.jpg
  Archive:  new.jpg
  warning [new.jpg]:  1557 extra bytes at beginning or within zipfile
    (attempting to process anyway)
    Length      Date    Time    Name
  ---------  ---------- -----   ----
          0  2022-04-28 21:53   stuff/
          5  2022-04-28 21:53   stuff/a
          5  2022-04-28 21:53   stuff/c
          5  2022-04-28 21:53   stuff/b
  ---------                     -------
         15                     4 files
  $
It works because most zip tools today will ignore all bytes before zip's magic number sequence, because concatenating a zip onto the end of something else has been common since DOS days. So almost every tool can find the correct offset - it's easy, as you pointed out.

Now, it can break if your "other" file happens to include the magic bytes. But that's rare enough that you only have to be aware that it can happen.

The magic bytes sequence in zip files is 4 bytes long, one can probably use this to compute the probability that a file of size N randomly contains these bytes.
A file of N bytes has N-3 different places for a 4-byte sequence to start.

A 4-byte sequence has 2^32 possible values. For the file not to contain the zip magic, all N-3 positions would have to have one of the 2^32-1 non-zip magic values. The probability that it doesn't contain a zip magic is then

P(nonzip) = ((2^32-1)/(2^32)) ^ (N-3)

And the probability that it does have a zip magic is P(zip) = 1-P(nonzip).

A 1 gigabyte file has about a 20% chance to contain a zip header. A 10 gigabyte file has about a 90% chance.

(Maybe?)

The chances are a little more likely, as there are two different 4-byte sequences that can identify a zip file. (Empty and non-empty).
I was curious and yes, I reproduce your numbers.

A robust zip decoder can beat those odds.

It can bail on a nominal start position by considering a bit more than the local file header signature magic word.

The next two bytes is a minimum version needed to extract and its legal values are sparse. A bit further comes 2 bytes giving the compression method which also has sparse values. I'd guess sparse values (small integers) are more likely to be found in a "random" non-zip stream but would still reduce the collision probability.

Then there are CRCs. These can greatly reduce the collision probability at the cost of the decoder doing speculative work which gets thrown away if a CRC fails to replicate.

My colleague was doing this to get code and files out from his company via email by appending base64 encoded files to a png.

However Gmail now rebuilds images to protect against malicious code and it completely strips the appended files from the image.

Edit: he told me it was because his boss had journalling turned on and saw every email sent and received in the company and he thought it was funny to bypass the boss for personal stuff.

>Have you ever thought of hiding a photo inside another photo?

No? Is there any use for this besides people sharing Child Sexual Abuse imagery without being detected?

Al Qaeda was hiding documents inside porn videos they were passing around. I'm guessing if you can find a video host that doesn't transcode the original file, you could publicly post these videos with special keywords for your comrades to discover.
It's a common format for savedata in the indie game scene. You place the game data within a screenshot of the game. It can make it easier to share state, and be more easily human-identified among other saves.

Hiding one thing inside another doesn't necessarily require secrecy as part of the intent.

I see your point, but that's not really a photo inside of another photo. What kind of secret photos do people need to be hiding inside of other photos?
Maybe people just want to have some fun? Send a secret picture only to their friends? Or maybe they want to send an image while hiding it from a government censor? I'm sure you can come up with more examples if you use your imagination.

Besides complaining about the potential use for child pornography is bizarre. If someone wanted to secretly send child porn to someone else, they could just encrypt it. It would be far more effective than this image packing method.

>If someone wanted to secretly send X to someone else, they could just encrypt it. It would be far more effective than this image packing method.

You're making a case against steganography?

No and I'm a bit unclear how you inferred that. I am, however, making the claim that embedded images similar to the blog post are much easier to discover than it is to break encryption. Does that clarify things for you?
A reporter might want to hide images that could be considered regime critical if they might be searched. Lots of nice pictures of healthy patriotic people, no suffering and starving people, empty shelves or grass stealing beggars to see.

Or without leaving the country you might want to hide pictures of animal abuse if you took them without permission from the owner, in some places documenting animal abuse is even more illegal than committing it. Look at all those funny cat pictures, no cows rotting in their own shit to see officer.

You could do that by hiding a document in any other document with existing tools. A picture in a picture is pretty specific to the format of most online media consumption.
The fact that "Child Sexual Abuse imagery" is the only use case your brain could think of for Steganography says a lot about you. I wish I could report and block you a thousand times.
Considering how a technology could be mis-used shouldn't be frowned upon.
Report me for what? Being realistic about what a "hide a picture in a picture" technology is probably going to be used for? What an extreme of overreaction.

That's like inventing a "remote roadside detonation device" and claiming it will only be used for parades to activate confetti payloads. It's naive.

An invisible way to hide a signature comes to mind. Until the ownership comes into question no one will be aware that the image itself contains all proof needed.

You could do something like Eurion and hide a pattern that only copiers can identify. Or do the same as color printers and encode hardware and user information as a pattern.

DOOM 2016 hid satanic images in its sound files instead of other images, of course that was only an easter egg and not really useful outside of confirming that computer games are evil.

(comment deleted)
i assume you could do this with a one time pad to transform the image to the new image
I remember seeing an image a long time ago that revealed a different image when you highlighted it. But I could never find any references to the technique since then. Does anyone else remember something like this?
I had another idea for steganography in Jpegs specifically. So in Jpeg there is something called the Quantization Table that's responsible for weighting all the AC values in each 8x8 block. When you encode, you divide the DCT values by the corresponding DQT value so a large quantization value has a greater chance of reducing the DCT to 0, allowing us to truncate the high frequencies (we want this). To decode we just multiply by the corresponding quantization value and run the inverse DCT.

But nothing prevents us from putting 0s in the Quantization table. And any pixel put in those values wouldn't contributed to the rasterized image. So we can cut off some of the high frequency bins entirely and then store whatever in them.

Steganography is so exciting, my first exposure was on 4chan back in 2006, you could use image hosting sites to hide and secretly host tons of things. SOF/EOF and such to look for that and more... :)
If you run image recognition algorithms on this, will they recognize the outer image or the inner image or both or none?

Btw this is fascinating!

The next step would be to hide an animation within another, in the APNG format. But I ignore if there is any compression that would make this impossible.
Would it be feasible to have a machine readable image like a QR code as the obscured image, so if people took a photo of a poster some metadata about the poster could be exposed to the camera app to then be passed onto the user?

Or does this technique rely on having access to the original digital image, and too much information is lost over the analog gap?

You would need camera sensors that are sensitive to the minute changes in color this technique causes. Digital cameras use color filters [1] to capture that information, and these are more aligned with how the eye sees color. I’d imagine that would introduce the opportunity for losing what little information there is.

[1] https://en.wikipedia.org/wiki/Bayer_filter