C'mon, I Want Lolcats!
Abstract
This EPUB 3 proof of concept demonstrates how one can obfuscate data
inside an EPUB 3 container, and display it at runtime via JS. In this
example, the base64 representation of an image is embedded into
<p>
identifiers, and a tiny JS is used to reassemble and
display it at runtime.
Download
You can download the EPUB 3 file from here.
This demo is released under the terms of the MIT License.
Description
The goal is to obfuscate an image inside an EPUB 3 file so that it is difficult to detect it by just looking inside the EPUB 3 (ZIP) container. In particular, we do not want to include the image as a file (as one normally does, listing it in the OPF manifest), nor having it "plainly" coded in base64 inside an XHTML page (which would make it easily detectable). Note that the same technique can be applied to show text, links, images, audio, video, etc.
The idea is to break the base64 representation of the image into pieces, "hiding" them as element identifiers. A small JS will read these identifiers at runtime and it will manipulate the XHTML page DOM to display the obfuscated image.
The second chapter of the above eBook contains several dummy ("lorem ipsum") paragraphs, each of them looks like the following one:
Each paragraph id
contains a piece of the base64
representation of an image. Unfortunately, just breaking this base64
representation into pieces is not enough, as they might contain
\
, +
, and =
(which are not valid
characters for XHTML identifiers) or a digit [0-9]
as the first
character (which is not allowed in XHTML identifiers).
To make it a legal XHTML identifier, the first problem is solved by
translating /
, +
and =
into
_a
, _b
, and _c
, respectively (better
camouflage might be achieved in several ways), while the second problem is
solved by prepending an underscore (but it can be a randomly generated
character in [A-Za-z0-9_]
for better camouflage) which will
always be discarded when reassembling the base64 representation.
The XHTML page contains the following code:
where init_popups()
seems an innocent name, right? Well, try
loading the eBook in a supported reading system (see below), and you will get
a fluffy surprise!
Supported Reading Systems
This example has been tested and it runs "correctly" in Apple iBooks on iOS (EDIT 2014-02-06: it does not work in iBooks on Mac OS X), Readium, and Calibre. The image is also shown by Kobo iOS app, but it is appended at the very bottom of the page and only its upper half is displayed.
This example should work in any Webkit-based browser as well.