逆向Notability文件格式,逆向工程其实也不难! – 作者:ijzmesec

本文虫虫编译,源blog地址请参考。原作者Julia Evans是一个科技漫画作者。有很多很不错的编程漫画作品,可以观看学习。

5.png

我日常喜欢画些有关编程的漫画。 在上周四,我买了一个iPad 和Apple Pencil,因为Apple Pencil是一个非常好的绘图工具。我开始使用iPad的Notability应用程序,他看起来非常不凑。但是我遇到了一个不爽的事情:

我使用的Android应用程序中有很多的原始图片,但是用的格式是Squid!

Notability可以导入pdf,但它们会变成只读,你可以在其上绘制,但不能编辑它们。很烦人,不是吗?

趣味问答开始:

Julia:“我想把我的旧图纸转换到新的app里,但是没有办法做到这一点!”

Kamal:“那么如果你反向工程Notability文件格式呢?”

Julia:“呃,听起来好像需要很长时间”

Kamal:“也许只要花上一个小时,看看会发生什么!”

Julia:“好吧!”

本文旨在弄清如何将SVG转换为Notability的原生格式(.note)。这是一种专有格式,而且好像还没有人对其进行过反向工程,所以我们的从头开始。

如果你是伸手党,想直接用现成的程序SVG转换为Notability,可以参考github repo:svg2notability。它就用了不到200行的Python代码来实现。

我会写出逆向工程这个文件格式的过程,因为它并没那么困难,逆向工程往往看起来很可怕,有点不可亲近。但是我昨天就开始做了,直到今天晚上,已经做了一些成果,已经足够实际使用。

在这篇文章中,我会解释如何破解Notability的 .note格式的构的。

Ox00从.note文件开始

我从APP中导出了一个.note文件,将它放入Dropbox,并将其复制到我的Linux工作机上。这简单,这个文件是template.note。

 Ox01 解压缩文件

什么是.note文件呢?找出答案的方法就是用file命令探测他。原来它是一个zip包:

$ file template.note

template.note:Zip archive data, at least v2.0 to extract

$ unzip template.note

 解压缩到名为template /的目录中。这里是它里面的文件组成:

$ find template/

template/

template/thumbnail

template/Assets

template/Session.plist

template/thumb3x.png

template/Recordings

template/Recordings/library.plist

template/thumb2x.png

template/thumbnail2x

template/metadata.plist

template/Images

template/thumb6x.png

template/thumb.png

不错,好整洁!咦,有个.plist文件?

0x02解码.plist文件

通过谷歌(和file)搜索,我们得知.plist文件是某种苹果文件格式。谷歌显示,可以为XML格式或二进制格式。这里他是苹果二进制格式。

$ file template/Session.plist

template/Session.plist:Apple binary property list

 我但是对此有点担心,但还有一些谷歌搜索显示有一个名为plistutil的Linux工具,我可以在对其进行转化。先安装plistutil。

我吧所有的二进制.plist文件转换XML,看看它们,很清楚的表明template/ Session.plist是具有绘图数据的文件。一旦将其解码为XML,你可以看到它在这里的样子:notability_session.xml。

你怎么知道这是绘图数据的地方,Julia?那么,它的内容内容这些非常动人关键字,如“curvespoints”。比如这个:

 <key>curvespoints</key>

<data>

mgG+QjOrB0NmuUBDVT3MQgA5kUNEJIlCTBXCQ2YWDEIAT7JCM4tqQ+YFUEMzGVlDJnKj

QzOnR0Na4d5DMzU2QzMzukKafLZDM5dZQ2aDrkNmCqtDM4qmQzNJ6UMAkZ5DZpadQjPQ

A0SFx51CsM4DRHjvnUI7zQNEsRCeQrTLA0QiU55CpsgDRKl6nkJUxQNEzZqeQs3AA0Sv

rp5CEr8DRHW3nkIdvQNEM82eQma4A0RNHJ9CrqkDRNV2n0KUmANEmtGfQs2IA0QoPqBC

p3UDRJugoEINZQNEANagQs1eA0SKIaFCC1QDREOEoULIRgNEzQyiQoA1A0TpVKJCUSsD

ROCWokKvIgNEzcmiQrMdA0SVk6NCtAgDRH10pEJr9gJEzZOlQmbfAkTyaadCkrUCRFb8

qUKYewJEmjCtQmY+AkTkaLBCSQICRKEqtEIkyAFEAPi3QjOSAUS+RbtCMGMBRK6lvkKk

MwFEANDBQmYDAURBQMZCHb0ARCxqykKSdgBEzQDPQrMwAET6vtNCwdL/Q34M2UJwPv9D

mT7eQpm6/kNsXuNCcjr+QzQE6EIV2f1DM7vsQjNi/UMSDu9C6CT9Qztz8UIY4fxDmRD0

QpmY/EMwL/ZC3F/8Q0Fu+EKoJPxDM8L6Qmbl+0N9tf1Ck5P7Q6JnAENsOvtDmu4BQ5nf

+kOgxgJDQK36Q0OWA0MCe/pDmmQEQ5lF+kNbgQVDQ/v5Q6yaBkMkr/lDZr0HQzNk+UPB

</data>

有人可能会认为这个“curvespoint”数据代表了文件中曲线上的点。答对了:它的就是。

 0x03解码曲线上的点

这听起来很直接,但在实际的工作中,这是让我最头疼,最讨厌的部分。以下是我如何解读这个“curvespoints”的内容:

 1.发现他是base 64编码。这一部分很简单:我之前使用过base64编码数据,二进制数据通常是在文本文件中编码的。酷!

2.在hexdump中的查看他数据

3.混淆(“这只是随机字节?!!?我怎么知道这意味着什么?”)

4.试着看看它是否是msgback(no),bencode(no)。感到困惑。抱怨。重复一个小时左右。

5.最后,等等,突然想到,如果它只是一个32位浮点数阵列?事情将会变得简单,实际上,确实是这样的!。

6.尝试将其解码为32位浮点数组

7.OK,他工作正常。

下面是来解码这个一个32位浮点数的Python代码。 Python中带有一个解析plist文件的内置模块。 非常有用

import subprocess

import plistlib

import struct

def unpack_struct(string, fmt):

    return struct.unpack(‘{num}{format}’.format(num=len(string)/4, format=fmt), string)

plistlib.readPlistFromString(subprocess.check_output([‘plistutil’,’-i’, ‘file.plist’]))

curves_points= pl[‘$objects’][8][‘curvespoints’].data

unpack_struct(curvespoints,’f’)

这里有一些来自于我文件的浮点数。这些看起来非常清晰,就是曲线上的点:它是一个浮点数组,每个连续2个浮点组都是曲线上的一个点。干的好!

(407.59869384765625,

 396.6827087402344,

 408.05926513671875,

 396.3546447753906,

 408.2127990722656,

 396.2452697753906,

 408.3787536621094,

 396.1249084472656,

 408.55938720703125,

 395.9921875)

0x04解码其他字段

解码其他字段很简单:

curvenumpoints:32位整数数组,它是每条曲线上的点数(unpack_structcurves [‘curvesnumpoints’].Data, ‘i’)),

curveswidth:32位浮点数组,每条曲线的厚度

curvescolors:32位RGBA值的数组(0x00FFEEFF是十六进制代码#00FFEE,最后一位是不透明度)

curvesfractionalwidths:可变长度曲线的宽度乘数。我不关心这些,我把它们全部设置为1.0。

eventTokens:不确定,我只是将所有这些设置为浮点数1.0,它似乎都工作正常

0x05在图上绘制点数

 为了确保这些点实际上是点,我要把他们绘制在图上,在本例中,我实际上是使用了一个源于zine的关于你和你经理的对话。以下是它的样子:

1.png

非常酷!!!!我对我的成功感到非常激动。于是下午5点,我有时间去朋友家吃晚饭,所以我这样做了。

0x06生成.note文件

好的,现在我们有一些眉头,我们知道这个文件格式是如何运作的。我们如何生成这种格式的文件呢?

 基本的步骤如下:

1、从现有的空的.note文件开始。

2、除了Session.plist文件(绘图数据所在的位置)之外,所有内容都保持一致。

3、设置curvesnumpointscurveswidthcurvescolors等数据

4、将它用Zip打包,将其导入我的app,并希望它能正常工作!

 有一种debug策略帮助我一路成功,那就是我尝试重新生成已有的.plist文件。我得到了我认为它表达的点的列表,并且自己生成了curvesnumpoints等字段,并确保它们与Notability对这些文件的真实数据相匹配。然后我进行单元测试!

一路上有很多奇怪的工件和错误,但是这篇博文已经很长了,我不认为解释这个很有趣。

0x07 结果

结果如下!首先,我输入到我的svg2notability程序中的SVG如下所示:

2.png

在我转换它之后,它在Notability中!它看起来基本相同!而且我可以轻松编辑它,这就是要点。颜色,样式等一切都正常!

3.png

0x08 未尽的部分

1、生成具有多个页面的文档(没有尝试)

2、绘制正方形,我的一些绘图有完美的正方形,并且还有一个问题,我还没有制定出来

3、在Notability中更改纸张尺寸以匹配原始纸张尺寸。相反,我只是缩放宽度以匹配Notability的默认纸张宽度,这已经可以了,但还可以更好。

 0x09 后记

 我认为使逆向工程不那么难的事情是,开发人员重复使用代码!人们通常不会发明完全自定义的文件格式!这里没有任何东西真的很复杂,它只是一些现有的标准格式(zip,苹果plist,一组浮点数数组)以非常简单的方式组合在一起。

 这个事情很有趣,从一个看似棘手或非常繁重的任务开始, “等等,我是一名程序员!!”,并设法使用编程的力量来达成我想做的事情(至少是这样)!

我发现所有这些移动绘图应用程序(Squid,Notability,Goodnotes等)都使用专有文件格式,如果没有逆向工程,就不能在对其互相转换。但逆向工程是就可以! squid_decoder反向工程了Squid格式(它基本上是一个谷歌缓冲协议)

 如果你想觉得看文章费劲,直接看代码:  https://github.com/jvns/svg2notability

来源:freebuf.com 2018-04-13 09:29:45 by: ijzmesec

© 版权声明
THE END
喜欢就支持一下吧
点赞0
分享
评论 抢沙发

请登录后发表评论