Reverse Engineering Evernote Penultimate (or: When is a picture not a picture?)

In this post Alex Caithness takes a look at “Penultimate” on the iPad and discovers that a picture paints a thousand words… but only once you work out how that picture is stored.

Recently we came up against an iPad note-taking application by the name of “Penultimate”. As a user it’s actually really quite a nice app to use: you can create multiple “notebooks” each with as many pages as you require on which you can jot down notes, draw diagrams or just doodle with a stylus or your finger. For a user it’s nice, simple and intuitive, for an intrepid forensic analyst, it’s not quite as straight-forward…

Penultimate Hello World Screenshot

Penultimate Screenshot

After installing the application on a test iPad, creating a couple of notebooks and having a doodle in each of them, I performed an extraction of the device. Poking through the application’s folder, this is the layout of the files which we can acquire with a backup-style acquisition:

 │     com.cocoabox.penultimate.plist
 └───Private Documents
 │     notebookList
 │     notebookListBackup
 │     100F53F2-BD1F-4046-8104-714E42264DAE

Now, ideally what we’d liked to have seen at this point are some image files, a nice friendly JPEG, GIF or PNG or two would have been just lovely. But no, it’s not going to be that easy (and, in fairness, if it had been I wouldn’t be bothering with this blog would I?).

So what do we actually have? Well, we can see the familiar “Library” folder in which we find the (also familiar) “Preferences” folder which contains a property list, the contents of which are mostly mundane (though we do have application launch counts and dates which may be of interest in some situations). More interesting is the “Private Documents” folder and the files and folders which are contained within it.

In the root of the Private Documents folder is a binary property list file named “notebookList”. It is a ‘NSKeyedArchiver’ plist, which means, as we discussed in a previous blog, it needs some additional processing in order for us to see the actual structure of the data. Luckily I had PIP and the “ccl_bplist” Python module to hand, both of which can perform that transformation. With the data structure untangled I proceeded with digging around to see what, if anything, we could extract from the “notebookList”.

Among some less interesting data, the root object contains a list of the notebook objects which are stored by the device, under the “notebooks” key.

notebookList in PIP

notebookList in PIP

Each of the notebook objects (which are represented by dictionaries in the property list) contain the keys: ‘name’, ‘title’, ‘pageNames’, ‘created’, ‘modified’,  ‘changeCount’, ‘blankPages’, ‘creatingDeviceId’, ‘editingPageName’, ‘pageDataIsCooked’, ‘versionMajor’, ‘versionMinor’, ‘pagePaperStyles’, ‘paperStyle’, ‘imported’ , ‘coverColor’, ‘originalName’.

The first few there are of immediate interest: the value of “title” does indeed contain the title of the notebooks that I created during my testing and the “created” and “modified” timestamps also ring true. The values of the “name” keys are familiar as well, albeit for a different reason; in my test data we see the “name” values “DD47D226-0CB3-460F-A0F9-3A7E2A795B3D” and “23FDA4FF-CE5E-4353-8D9A-B0C3E3E8AAE7” – matching the directory names that were extracted underneath the “notebooks” folder (see above). Beyond this, the “pageName” key contains a list of values which also match the names of files in each of the “name” directories.

So, with the “notebookList” file we have some useful metadata and a helpful guide to how the other files are organised, but there’s still no sign of the content of the notes themselves. Delving deeper into the folder structure, our next stop is one of the files which was named in the “pageName” list mentioned above.

Opening one of the “page” files we find another “NSKeyedArchiver” property list. After unravelling the structure of the file we find a top-level object containing further metadata (including a “blankDate” which appears to match the “created” timestamp reported in the “notebookList” and the dimensions of the note) along with a list of “layers”. Each of the “layer” objects (again represented by dictionaries) have keys for the layer’s colour (more on that later) the layer’s dimensions and a list of “layerRects” – sections of the layer where the user has drawn their notes; and that’s where we finally find the image itself.

Sort of.

Structure of the page object

Structure of the page object

Each of the “layerRects” objects are represented by (and this shouldn’t be a surprise by now) a dictionary. There are two keys: firstly “rect” which contains a string of two sets of “x,y” co-ordinates: the bounds of this layerRect on the page. The second key is “values” which requires a little extra explanation. As noted in my previous post on NSKeyedArchiver files, their function is to represent a serialisation of objects; the object under the “values” key is a “CBMutableFloatArray” which is programmer talk for a list of floating-point numbers. With this in mind we quite reasonably expect to see just that – a list of floating point numbers; but no, instead we get a data field containing binary data! As nothing else in this data had been straight-forward this was disappointing, but by this point didn’t surprise me. Floating-point numbers (like any numerical data) can be represented quite happily in binary, so I set about trying to turn the binary data into a list of floating-point numbers. I extracted one of these data fields and with a nice Python one-liner did just that:

>>> struct.unpack("<18f", data)
(282.0, 589.0, 5.506037712097168, 281.8666687011719, 588.2999877929688, 5.506037712097168, 281.73333740234375, 587.5999755859375, 5.506037712097168, 281.5999755859375, 586.9000244140625, 5.506037712097168, 281.4666442871094, 586.2000122070312, 5.506037712097168, 281.33331298828125, 585.5, 5.506037712097168)

So now we can see the numbers, but what did they mean? The meaning becomes clearer if we group them into threes:

282.0, 589.0, 5.506037712097168
281.8666687011719, 588.2999877929688, 5.506037712097168
281.73333740234375, 587.5999755859375, 5.506037712097168
281.5999755859375, 586.9000244140625, 5.506037712097168
281.4666442871094, 586.2000122070312, 5.506037712097168
281.33331298828125, 585.5, 5.506037712097168

What we have here is sets of x-y co-ordinates and another value (the meaning of which will become clearer later). So, here, finally is our drawing; stored as a list of co-ordinates rather than any conventional graphics format – the combination of the points in the “layerRects” in each of the layer objects gives you the full picture.

But how to present this data? A list of co-ordinates like this is of little to no use; we want to see the image itself. So I got to thinking: how does the application treat these co-ordinates? Well, when the user draws in the application they are essentially ‘painting’: moving a circular ‘brush’ around the screen making up the lines in the drawing, so if I was able to plot a circle at each of these co-ordinates perhaps I would see the picture? This thought process also gave me an idea as to what the third value in each of the co-ordinate groupings might represent: part of what makes the drawings look natural is that the “line” that is drawn is not of a uniform width, it grows and shrinks with the speed at which the finger or stylus moves, giving an impression of weight – perhaps the final value related to this?

So how to plot these co-ordinates? First of all I looked at various Python imaging libraries (PIL and PyGame both came on my radar), but there were issues with both (especially with PIL which still lacks a proper Py3k port) so I turned my attention to an alternative solution: SVG. SVG (Scalable Vector Graphics) is a graphics format specified by the W3C; it uses XML to describe 2D graphics. Because SVG just uses XML, no imaging libraries would be required; I could simply generate textual mark-up describing where each of my circular points should be plotted on the screen. Taking the data above extracted above as an example, the mark-up would be along the lines of:

<!DOCTYPE svg>
<svg height="865" version="1.1" viewBox="0 0 718 865" 
     width="718" xmlns="">
    <circle cx="282.0" cy="589.0" 
            fill="#000000" r="5.506037712097168"/>
    <circle cx="281.8666687011719" cy="588.2999877929688" 
            fill="#000000" r="5.506037712097168"/>
    <circle cx="281.73333740234375" cy="587.5999755859375" 
            fill="#000000" r="5.506037712097168"/>
    <circle cx="281.5999755859375" cy="281.5999755859375" 
            fill="#000000" r="5.506037712097168"/>
    <circle cx="281.4666442871094" cy="586.2000122070312" 
            fill="#000000" r="5.506037712097168"/>
    <circle cx="281.33331298828125" cy="585.5" 
            fill="#000000" r="5.506037712097168"/>

Each “circle” tag has an x and y co-ordinate (“cx” and “cy”) a fill colour (here expressed as an html colour code – black in this case) and a radius (“r”). Running some tests gave some good output; but things weren’t quite right, firstly, and most importantly, the image was mirrored in the y-axis, presumably caused by a difference of opinion between Penultimate and SVG as to where the y-axis originates, an easy fix (just subtract the ‘y’ value from the height of the image and use that value instead). Also, the lines in the writing all looked very chubby, making writing very tricky to read. Theorising that this was caused by Penultimate storing diameters and SVG requiring radii, I halved the value which improved things, but comparing the output with what I could see on the screen things still weren’t quite looking right so on a whim I halved the value again which made things look right (I’m not entirely sure why it should be the case that you have to quarter the value – it may be to do with penultimate adding a ‘feathered’ fade to the brush which increases it’s diameter though).

I created a proof-of-concept Python script to check that my thinking was correct and I was pleased to see that the output now matched what I could see on the iPad’s screen, save for the fact that the iPad was in glorious Technicolor and my script’s output was monochrome. I mentioned previously that the “layer” objects contained colour information under the unsurprisingly named “color” key.

The object stored in the “color” key has values for red, blue and green – each one a value between 0 and 1. Those readers who have had even the briefest dalliance with graphic manipulation programs will be familiar with colour-sliders: combining red, green and blue in different proportions in order to generate different colours, which is what these values represented. My SVG generated output was working with HTML colour codes which are made up of 3 bytes, each representing an amount of red, green and blue, this time using values from 0x00 to 0x0FF, to get colour into my output, all I had to do is multiply 0xFF by the correct value from the “layer” object’s colour fields and recombine those values into an HTML colour code. I modified my script and now the output reflected both the form and colour displayed by the App on the iPad.

Comparison between iPad and script output 1

Comparison between iPad and script output (1)

Comparison between iPad and script output 2

Comparison between iPad and script output (2)

Working on extracting data from Penultimate was a particularly enjoyable experience as it required a combination of a number of different concepts and led to the use of a number of different technologies to create a solution to automate the extraction of the data, which when it all boiled down was satisfyingly simple.

And as to the question: when is a picture not a picture? Well, quite simply: when it’s a series of serialised floating-point co-ordinate triplets representing points on a page, broken up into rectangles on a layer on a page which is stored in a NSKeyedArchiver property list file (obviously!).

If you have any questions, comments or queries regarding this post, as always you can contact us by dropping an email to or by leaving a comment below.

Update: As requested I’ve uploaded the script for research purposes. You can find it here: 

Alex Caithness, CCL Forensics

New Epilog Signature files released

Epilog Signature files allow users to add specific support for new databases they encounter and although they are designed so that Epilog’s users can create their own signatures when the need arises, CCL-Forensics are committed to updating and releasing a sets of signatures, pre-written and ready to use.

In this new release we have had a real focus on smartphones adding support for:
• iOS6
• Android 4.0 (Ice Cream Sandwich)
• Android 4.1 (Jelly Bean)
• Android 3rd Party Applications
• iOS 3rd Party Applications
• Skype

We always welcome suggestions for signatures that you’d like to see added to the signature collection so please get in touch on

For more information on epilog please visit our website –

SQLite analysis for forensic practitioners

epilog‘s developers have put together a one-day training course to help you to get the best possible results from digital investigations involving SQLite databases.

The course covers the basics of epilog and demonstrates how to deal with SQLite logically, as well as covering how to optimise results and advanced use of the tool. It will help you to get more from your investigations.

For example, the iPhone web cache is stored in an SQLite database. In a recent case, epilog recovered and presented nearly 5,000 entries from the web cache, where only 400 live (visible) entries were shown – including both textual and binary data. The tool streamlined the process by identifying the tables from which the data originated, and then allowed the investigator to use the “export to insert statements” functionality to make these records live again. This enabled the deleted cached records to be parsed and processed.

Our training course will teach you how to do this, and much more.

It takes place on February 7, 2012, at our offices in Stratford-upon-Avon. It’s a one-day course, costing just £250+VAT per person – a bargain in anyone’s book. Call us now on +44 (0)1789 261200 or email for more information or to book a place.

Alex Caithness

epilog developer

Recovering chat logs with epilog

Alex Caithness, epilog‘s developer and programmer, has put together a short video to demonstrate how epilog can recover chat log messages – in this case, from an Apple iPhone.

Epilog is available for free trial download from

Dunk your cookies in our software

Cookies are often seen as the poor cousin of digital evidence, but they can provide a wealth of information for digital investigators – including how often, from where and how a user visited a certain site – as well as the search terms used to find it.

So how can we access this treasure trove of knowledge?

By using a piece of software called dunk! which covers all the main PC internet browsers (Chrome, Firefox, Safari, IE, etc.) and a wide range of mobile browsers.

The inspiration for dunk! came after conducting an examination of an iPhone during which we found that evidence for the web history and cache was thin on the ground – although we were getting some interesting key word hits in the cookies.

Previously, analysts had been dumping cookies into a straightforward table view, but not looking at the structure of the cookies’ values. However, in this case all the interesting key words fell inside what were found to be Google Analytics cookies. The nice thing about these cookies was that, unlike many cookies where the structure is proprietorial, these were consistent between all sites and contained really interesting insights into a user’s web activity.

We wrote a program enabling us to view all the cookies at once, and where known structures (such as Google Analytics) were found, automatically parse them – and we designed it to support as many browsers as possible.

But that’s not all it does; dunk! can detect session cookies which may contain usernames, email addresses, and sometimes even passwords, allowing investigators to build the fullest picture possible of browsing habits.

The interface allows the data to be filtered, searched and exported. In a nutshell, the software does the following:

  • Processes cookies from PCs and mobile devices
    • Internet Explorer 5+
    • Mozilla Firefox 3.x
    • Mozilla Firefox 4.0
    • Google Chrome
    • Safari browser
    • Opera 5+
    • Apple “binarycookies” format
    • Android browser
    • Flash cookies
    • Nokia 40 browser
  • Parses Google Analytics cookies
  • Parses Adobe Flash cookies
  • Enables investigators to search and filter evidence
  • Detects session cookies which may contain usernames, email addresses, etc.
  • Outputs to TSV and XML file formats

Open the cookie jar and take a detailed look at what’s inside.

Alex Caithness

Dunk! Developer

Updated signature files for epilog

CCL-Forensics’ developers are constantly adding new files to increase the capability of epilog, and the latest signature files are now available for download, free of charge.

These new signature files now contain support for Apple iOS5.

We also welcome suggestions for additions to future signature file releases. Please email us at

What is epilog?

For those who don’t know, epilog is a software tool which allows investigators to recover deleted data from the widely-used database format, SQLite. Take a look at the first of our epilog videos:

It was developed by CCL-Forensics and – put simply – it gives investigators access to more data which could prove crucial in an investigation.

Many devices (whether mobile phones, computers, satnavs or other devices) store data in the SQLite database format.

Data stored in this type of database can provide a huge evidential opportunity for investigators. Many “off-the-shelf” tools can be used to view the live records in the database, but epilog  extracts deleted and de-referenced data from the database files or across a disc image or hex dump.

epilog’s three recovery algorithms can be used on any SQLite database, regardless of the type of data stored. However, epilog signatures can be used to tailor its behaviour to a particular database.

Included with the initial release of epilog were signatures including:

  • Android (SMS, call logs, calendars, address book and others)
  • iPhone (SMS, emails, calendar, and others)
  • Smartphone third party applications (including Yahoo Messenger, eBuddy chat and others)
  • Safari (internet history and cache and others)
  • Mozilla (cookies, internet history, form data and others)
  • Chrome (internet history)