71 comments

[ 4.7 ms ] story [ 63.3 ms ] thread
Explanation please?
Took a look at the page source, and it's full of binary garbage. It looks to me that it's a JPEG image that has been slightly tweaked to contain just enough HTML to get a (lenient) browser to display it.
It's a JPEG with the HTML written in the comment field:

  # exiftool -b -comment <(curl -s http://lcamtuf.coredump.cx/squirrel/)
  <html><body><style>body { visibility: hidden; } .n { visibility: visible; position: absolute; padding: 0 1ex 0 1ex; margin: 0; top: 0; left: 0; } h1 { margin-top: 0.4ex; margin-bottom: 0.8ex; }</style><div class=n><h1><i>Hello, squirrel fans!</i></h1>This is an embedded landing page for an image. You can link to this URL and get the HTML document you are viewing right now (soon to include essential squirrel facts); or embed the exact same URL as an image on your own squirrel-themed page:<p><xmp><a href="http://lcamtuf.coredump.cx/squirrel/">Click here!</a></xmp><xmp><img src="http://lcamtuf.coredump.cx/squirrel/"></xmp><p>No server-side hacks involved - the magic happens in your browser. Let's try embedding the current page as an image right now (INCEPTION!):<p><img src="#" style="border: 1px solid crimson"><p>Pretty radical, eh? Send money to: lcamtuf@coredump.cx<!--
It also uses an (non terminated - AFAICT) HTML Comment to hide the rest of the JPEG data.
Yes but it is not necessary because everything except absolutely positioned div is hidden anyway.
> non terminated - AFAICT

Yes, it shows up as all green in Safari. And:

    $ { curl -s http://lcamtuf.coredump.cx/squirrel/?1 | grep -- '-->' ; } || echo "Not found"
    Not found
I suspected it was something like that: the "meat" of the HTML and JPEG data being contained in each other's comment fields, since that's how many quines work. I don't quite know enough about the JPEG file format to be confident about it, though.
Here is the output from the handy `file` BSD utility which gave it away to me (see the comment field).

    JPEG image data, JFIF standard 1.01, resolution (DPI), density 300x300, segment length 16, comment: "<html><body><style>body { visibility: hidden; } .n { visibility: visible; position: absolute; ", baseline, precision 8, 1000x667, frames 3
Cool, but it's a chipmunk not a squirrel. Just saying!
A chipmunk is a type of squirrel.
https://en.wikipedia.org/wiki/Squirrel

> Squirrels are members of the family Sciuridae, a family that includes small or medium-size rodents. The squirrel family includes tree squirrels, ground squirrels, chipmunks, marmots (including woodchucks), flying squirrels, and prairie dogs amongst other rodents.

(TLDR, chipmunks are squirrels)

(comment deleted)
Hey - I'm the author of that page. Your comment is a common misconception, but the animal pictured is actually a golden-mantled ground squirrel. You can tell because the stripe doesn't extend to the eye. Thank you for subscribing to squirrel facts!
Oh! You're right. Confused him with an Eastern Chipmunk.
If you think that this is interesting, you should check out Daeken's Magister: http://demoseen.com/windowpane/magister.png.html

It's a PNG that's interpreted as HTML and loads itself as compressed JavaScript!

This links to a detailed article titled "Doomsday planning for less crazy folk". Should I try loading it as JS? :)
No, nothing special tech-wise, but very sane content about disaster planning!
EDIT: I realize that the subject of this thread is not a polygot, but I'm leaving this comment up in case it interests someone. :/

If anyone's interested in what these are called, they are called polygots.

> In computing, a polyglot is a computer program or script written in a valid form of multiple programming languages, which performs the same operations or output independent of the programming language used to compile or interpret it.

[1] https://en.wikipedia.org/wiki/Polyglot_(computing)

I wouldn’t call it a polyglot as that has to deal with computer programs, no?
It also doesn't have the same operations/output since one is a squirrel photo and the other is a webpage with English text.
I always thought it was called a chimera.
So, if I remember correctly Ange Albertini's nomenclature, chimeras are particular types of polyglots where a single data is disguised as different file formats. For example, consider a file that is both a JPEG of a picture and a PDF which contains the same picture, and the data of the picture is present only once in the file.
POC||GTFO issue 2 (from 2013) was a PDF and a bootable OS at the same time:

From section 8:

"A careful reader may have noticed that a bootable OS image was hidden in the last issue of PoC k GTFO, as one of the files in its dual PDF/ZIP structure (if you haven’t, download and extract it now!). This time, though, let’s hide it in plain sight. You will find by running ‘qemu-system-i386 -fda pocorgtfo02.pdf’ that the PDF file you are reading is also a bootable disk image."

https://greatscottgadgets.com/pocorgtfo/pocorgtfo02.pdf

And issue 3:

"This file, pocorgtfo03.pdf, complies with the PDF, JPEG, and ZIP file formats. When encrypted with AES in CBC mode with an IV of 5B F0 15 E2 04 8C E3 D3 8C 3A 97 E7 8B 79 5B C1 and a key of “Manul Laphroaig!”, it becomes a valid PNG file. Treated as single-channel raw audio, 16-bit signed little-endian integer, at a sample rate of 22,050 Hz, it contains a 2400 baud AFSK transmission."

Don't forget the issue that was a PDF, a ZIP, and an NES ROM that would print its own MD5 when run in an emulator
Any reading you can link to regarding how to accomplish stuff like this? I.e. valid pdfs that are also valid bootable images?
They usually document their tricks in the file itself. For example, see Chapter 8 in GP's link.
The last week i found this [1] thread by Notch. He is working in an entry to js13k [2] (a game jam about html5 games restricted to 13 KBs).

He bundled the whole source code and binary data used in the game/tech demo to use the in browser image decompression, avoiding to write a custom (de)compression code, saving KBs this way.

Then he just eval() the needed parts for each thing.

I found this extremely clever, game jam limitations, specially size ones, evolve into clever programming tricks that are interesting both to code and to look at.

[1] https://twitter.com/notch/status/1035811278520872960

[2] http://js13kgames.com/

While definitely cool, I wonder how effective this is. Code/random binary data should have different characteristics than image data.
It's very effective, because it means you get a really good compression algorithm for free (because it's already there in the browser).

You definitely won't save enough bytes with better input heuristics than the amount of code needed to decompress them if you're only working with 13Kb of data.

You really save bytes even though you need to include it as a base64 url?
(comment deleted)
It is not a base64 url, is base64 image data.
DEFLATE, which is used by PNG, is a general purpose LZ77-like compression algorithm suitable for all kinds of repetitive data.
PNG filters each horizontal line of the image data before running it through Deflate, with a pre-processing step.

Each of the possible filters is very simple, but the difference between a great PNG exporter, a mediocre one, and a trash fire is the use of a heuristic to decide which of the pre-processing filters should be applied to each line of output. libpng, the free implementation, includes a heuristic that does a fairly OK job, if you just don't implement a heuristic and use no filtering at all, the results are enormous PNG files as seen in turn of the century Adobe Photoshop. So, no, a general purpose compression algorithm isn't very good for image data on its own.

(Choose for yourself whether you think Adobe wanted to discourage use of a popular free image format in favour of licensed formats for which it held relevant IP, or their development team are just incompetent morons, or both).

> PNG filters each horizontal line of the image data before running it through Deflate, with a pre-processing step.

Yes, as a means of making the data fed into the compressor repetitive enough to benefit from the compression algorithm.

> So, no, a general purpose compression algorithm isn't very good for image data on its own.

That's not what I said.

Just so other readers don't mistake this for what it is: this is a pretty common technique in JS sizecoding and it's by no means Notch's invention (and he doesn't claim that it is).
When i read that i found it amazing and very clever, i honestly never thought if it was or not Notch's invention.

I am not really into javascript/frontend development, but following js13k on twitter showed me a lot of things you can do to gain KBs on the client side.

However, is this that common?

Thanks for the info btw.

In 1k sizecoding it's rather uncommon because usually the decompression code (i.e. load the png, read the pixels) is bigger than the savings. I never dove into 13k sizecoding but I bet the payoff is much better there. I wouldn't be surprised if all decent 13k sizecoding entries would do something like this. some compression for sure, and why not PNG then?
But what does the Unix "file" command say?

  squirrel: HTML document, ASCII text
BSD file(1) on both Linux and NetBSD. Solaris also identifies it as HTML.

  $ curl -s http://lcamtuf.coredump.cx/squirrel/ | file -
  /dev/stdin: JPEG image data, JFIF standard 1.01, resolution (DPI), density 300x300, segment length 16, comment: "<html><body><style>body { visibility: hidden; } .n { visibility: visible; position: absolute; ", baseline, precision 8, 1000x667, frames 3
file(1) version 5.32-2ubuntu0.1.
file knows...
/dev/stdin: JPEG image data, JFIF standard 1.01, resolution (DPI), density 300x300, segment length 16, comment: "<html><body><style>body { visibility: hidden; } .n { visibility: visible; position: absolute; ", baseline, precision 8, 1000x667, frames 3

so you get even more details...

It's a pity that phones recompress the JPG when doing Save To Camera Roll.

I'd like to build a system for distributing mini-apps as images, bypassing the App Store.

A JavaScript bookmarklet could be used to provide a basic "bootloader" that provides an "upload image" button. Then a binary representation of the HTML could be loaded from the image data.

The problem I had was lossy recompression - colours bleed across edges, so the binary data was corrupt after the first save. I'm still not sure how to work around that problem.

Some kind of redundancy?
Try to use metadata sections and hope they won't be dropped during the re-save?
My phone left the JPG entirely intact when downloading it. I suppose you're talking about iOS devices?
The first thing to cross my mind when I saw this was XSS vulnerabilities. Presumably there's nothing to stop this page running JS?
Assuming you can include JS in the file, I imagine it would only run if the file was being parsed as HTML at the moment, not when parsed as a JPEG. That's the main point here: this file can be interpreted in two ways, but the data in it is treated very differently and has different effects depending on the way it's currently interpreted.
Nice one! So is the trick that:

1. JPEG allows text comments

2. Browsers don't enforce correct HTML (alternatively, is "����JFIF,,��r<html>" correct HTML?)

3. And exif tools mostly work based on header & statistical analysis?

Or am I completely wrong here?

I think the most irritating thing about this is right-clicking on the image and selecting "View image", just to be confronted with the very same page as before, since the browser continues to interpret it as HTML.
On that topic, I recently wrote a tool to take a PDF file, an OCaml bytecode file (OCaml can compile to both byte or native code) and smash them together to create a file that is both a valid PDF and a valid bytecode.

https://github.com/Drup/bytepdf

It should be possible to also make this a zip file since they're read from the end by official spec.