
我们生活在一个美好的时代。 我们周围有大量技术:电话,计算机,智能手表和其他小工具。 每天,制造商都在向市场发布越来越多的设备。 他们中的大多数人注定是短暂而光明的(或并非如此):发行时有实力的营销公司,制造商提供1-2年的全力支持,然后慢慢被淘汰。 简单的设备在官方支持期结束后可以工作数年。 使用智能设备,情况会越来越难。 如果小工具在断开制造商的服务器/服务的连接后至少可以继续工作,那是很好的。 幸运的是,如果操作系统,驱动程序或其他软件的下一次更新没有超越兼容性。
不幸的是,根据悲观的情况,事件越来越多。 购买后的5-10年,我们手中拥有技术上完善的设备,但是由于缺乏软件支持而无法使用。 当然,损坏的小工具令人不快。 但是,如果用户数据格式不兼容,则更加令人不快。 如果设备停止运行,则可以认为此数据已丢失。 就我而言,还没有发生最严重的情况,但是警报铃声已经响起。
因此,有一个臭名昭著的Korg公司,它生产非常高质量的音乐设备。 2010年,我从该公司购买了合成器,将音乐作为一种业余爱好练习。 Korg微型工作站是相当先进的模型。 除其他功能外,它还带有一个音序器以记录其音轨,并可以将数据以专有SNG格式写入存储卡。 可以导出为通用的midi格式,但是几乎丢失了所有元数据:有关叠加效果和滤镜的信息,虚拟乐器的各种设置等。 我个人的主要问题是过渡到录制音乐想法的速度。 这个缪斯女神是一个异想天开的创造物,大多数时候,我只是通过即兴创作或演奏一些简单的作品而遇到一个有趣的想法。 在没有在菜单上徘徊的情况下,我按下记录按钮的速度越快,我越有可能重复并记录一个有趣的片段,将来它可能会成为成熟作品的一部分。 当然,这种方法并不完美,但是我们正在谈论一种爱好。 一种或另一种方式,在近十年中,我已经积累了大约一千个音乐草图和SNG格式的草图。
铃声以合成器一系列故障的形式响起,需要对设备进行闪烁。 而且我考虑过将所有累积的数据转换成Midi格式,因为这样可以更轻松地存储,组织和编辑它们。 在Google中搜索转换器没有给出任何结果。 各种论坛上都有很多请求,历史已经持续了20年,甚至更多。 我发现的只是别人的古老Windows实用程序,自然与我的文件不兼容。
然后,我决定尝试查看此SNG格式的全部含义? 也许里面有一些普通的MIDI数据,您可以轻松取出并保存?
尝试解决“额头”问题
因此,从合成器的说明中,您可以发现SNG格式是一种容器,其中存储了所谓的“歌曲”。 每首歌曲包含16个音序器音轨以及音乐数据,以及声音和效果的设置。 通过合成器菜单导出为Midi格式时,每个“歌曲”都将导出到一个单独的.MID文件,并且所有声音和效果的设置都将丢失。 因为 我以最简单的形式发挥了我的想法,没有任何效果,问题恰恰是大量的SNG文件和手动转换过程的不便。 让我们看看这个过程是否可以加速或自动化。
首先,让我们回顾一下MIDI数据是什么。 简而言之,这是一系列音乐事件:按下和释放键,按下和释放延音踏板,更改速度,音色(虚拟乐器)和其他参数。 每个事件都包含从上一个事件的时刻开始的时间增量和数据,例如音符强度和音高。 midi文件格式非常简单:除了标题和数据本身之外,几乎没有任何内容。
粉色是Note On事件。 淡黄色是时间的三角洲。 蓝色-音符关闭事件。让我们尝试在SNG文件中查找我们的Midi数据。 为此,请在合成器上编写一系列音符序列,并将其导出为两种格式。 因为 由于我们不知道音乐数据在二进制文件中的确切位置,因此我们将尝试使用不同的音符序列重复该过程。
在下文中,我将使用十六进制编辑器Synalyze It! 未来的功能将对我们非常有用。 同时,只需使用二进制比较功能。

实际上,只有“歌曲”的名称重合。 比较两个具有不同音符序列的SNG文件,我们可以大致猜测出音乐数据的确切存储位置,但是目前这对我们没有任何帮助-数据格式是不同的。 该文件本身比Midi文件大十倍,并且似乎包含许多其他信息。 您可以在前四个字节和其他一些行中看到KORG签名,包括“歌曲”的名称和分配给曲目的音色(音调)的名称。
解析数据块的结构
幸运的是,如果没有工具可以相对容易地分析和理解二进制数据的结构,则可以完成此操作。 相同的程序Synalaze It!将为我们提供帮助,使您可以创建并应用“语法”来分析二进制文件。
语法是一种分层的描述性结构,可让您以人类可读的形式表示二进制数据。 该程序允许您下载某些格式的语法。 例如,对于相同的MIDI:

对于SNG格式,预期没有现成的语法。 好吧,让我们看看我们可以自己从文件中提取什么。
让我们从标题开始。 通常,此部分包含文件签名,版本信息,数据块的大小和偏移量。 在比较了几个不同的SNG文件后,我们找到了不变的部分,并密切注意那些变化的部分

在语法编辑器中创建标题结构。 前4个字节显然是文件的签名。 假设以下4个字节是版本控制的。 接下来的几十个字节不会更改,也不会包含任何有趣的内容-我们将为它们创建适当大小的binaryData。 但是随后的乐趣开始了。 您会注意到偏移量0x13和0x1b的字节行为中的某些模式。 第二个似乎与文件中“歌曲”的数量相对应。 并且第一个也随着标头中数据量的增长而增长-这似乎是大小,只有倒数不是来自文件的开头,而是来自下一个字节0x14。 在此阶段,我们只能猜测数字数据的类型。 假设大小为UInt32类型,即 占用4个字节。 将它们添加到我们的结构中。 现在我们可以设置标题结构的大小(大小+ 20)。

让我们看看接下来会发生什么。 如果仔细查看,您会发现整个文件中散布了三个字母的缩写:SNG1,SDK1,SGS1,依此类推。 这些字符在所有SNG文件中都可以找到,因此我们可以假定它们是某些块的签名。 此外,在其中一个签名之前,我们的头衔非常成功地结束了。 比较以下4个字节在不同大小的文件中的行为。 可以看出,值随着数据量的增加而增加。

其他一些实验,分析和计算,以及下面的图片开始出现:

因此,我们的文件由一个相当简单的块层次结构组成。 有些父块可以包含多个子块。 有些叶块(用二叉树的术语表示)不包含其他块。
然后魔术开始了。
仅需几个语法结构,我们就可以完全解析块文件结构因此,使用以下字段创建DataChunk模板结构(大小显示在方括号中):
id:字符串[4]
尺寸:整数[4]
层次结构:整数[4]
数据:结构
现在创建一个继承DataChunk的parentChunk结构。 在层次结构属性中,指定固定值0x400-这是父块的标志。 确保选中“必须匹配”复选框。
同样,创建childChunk。 在这种情况下,层次结构将具有两个值:0x240100和0x100
将对parentChunk和childChunk结构的引用添加到数据parentChunk结构中-通过这种方式,我们创建了递归。
最后,在主节点中添加对parentChunk结构的引用。

parentChunk的数据结构中的元素顺序必须为Variable,还需要设置该结构的子级的最小和最大数目:分别为0和Unlimited。
让我们应用更改,瞧吧-我们的文件很好地解析到了主要块中

我们仍然对数据本身一无所知,但是现在我们可以更轻松地在文件中导航,并专注于查找所需的信息。
解析包含文件目录的块
为了进行培训,让我们尝试解析一些简单的块,例如SDK1。 显然,它包含诸如目录之类的内容-歌曲列表以及可能的一些偏移量/大小。

创建一个继承childChunk的sdk1Chunk结构。 我们将编辑ID字段,在“固定值”字段中指示块的签名。 不要忘记“必须匹配”复选框。 在块数据中,可以观察到一种相当明显的重复模式:“歌曲”的名称和迄今为止未知的数据。 请注意,重复片段的大小为64个字节。 另外,将文件版本与不同数量的“歌曲”进行比较,可以确定数字存储在前四个字节中。 使用简单的计算并做几个假设,我们在语法中获得以下结构的版本:

在这里,我创建了一个64字节的songInfo子结构,并指出了重复numSongs次的能力。 这是应用语法的结果:

进一步的文件分析仍然是技术问题。 我更改了“歌曲”的常规设置以及合成器上各个音轨的参数。 通过比较文件版本和各种更改,可以改进和完善语法。 经过足够多的此类迭代后,文件中几乎没有无法识别的数据。 我对过程有点不满意,并整理了文件的几乎所有部分,尽管原始任务并不需要这样做。
我会错过此过程的细节-将来,我们将直接关注音乐数据的分析。
但是在下一部分中会对此有更多的介绍。 在那里,我们将遇到一个有趣的数据转换任务(非常适合采访),尝试使用一个小的脚本来解决它,并听到一个非常不寻常的测试转换结果。
初步结果
反向工程二进制文件的需求可能会意外发生。 例如,要分析设备固件,从稀有数据格式进行转换,分析数字威胁,甚至是微不足道地修改游戏存档。 现代工具可让您快速有效地解决这些问题。 大约10年前,我正在研究笔记本电脑固件,此过程可能需要数周的时间。 然后需要手动编写脚本来分析数据块和布局结构。 使用新的部分自动化方法,我在短短几天内就创建了几乎完整的文件语法。
您可以通过搜索字符串来开始对二进制文件进行分析-它们可以提供第一个线索并加快分析过程。 通常,二进制文件由以分层或线性结构组织的数据块组成。 如果处理这种结构,则进一步的分析将容易得多。 文件头可以提示数据块的偏移量/大小。 在第一个阶段,将重点放在明显的结构和块的描述上是有意义的。 通过创建具有不同设置,参数和数据的文件新版本的能力,大大简化了分析任务。 与未知数据类型和其二进制表示形式的字节顺序(字节序)相关的困难很多。 我们将在下一部分中讨论这些问题。
推荐读物
安德烈亚斯·佩纳克(Andreas Pehnack)。 如何进行二进制文件格式分析