尝试在Python中解压缩/解码专有数据文件

时间:2014-08-28 19:56:03

标签: python text file-io io

tl; dr - 在尝试对专有数据库文件进行逆向工程时,我发现Wordpad能够将一些数据自动解码为清晰易读的格式。我正在尝试在python中实现该解码。现在,即使是Wordpad伏都教也不可重复。


准备好脑筋急转弯?

我正试图解决一些奇怪的问题。我有一个数据文件,它是科学仪器(Mettler DSC / STARe软件)程序的数据库,我正试图从实验中获取样本信息。从我在文件中挖掘,它似乎包括有关实验运行的明文,未加密信息以及数据。它是一个.t00文件,大小超过40 mb(它基本上存储了运行的所有数据),而且我对编码知之甚少(除了它看起来是任意的。它并不意味着是一个文本文件)。我可以在Wordpad中打开这个文件,可以看到我正在寻找的信息(样本名称,时间戳,实验参数),被实验运行数据包围(正如预期的那样,这看起来像很多gobbledygook,例如¶+ú@“< Ø@ DSSO @¨...)。看起来我基本上很幸运能够对内容有所了解,而我正试图复制它。

我可以使用基本文件处理程序将文件读​​入python,并使用正则表达式获取我想要的一些信息。 'r'vs'rb'似乎没有帮助。

def textOpenLines(filename,mode='rb'):
    with open(filename, mode) as content_file:
        return [line for line in content_file]

我可以获取该列表并搜索相关字符串并从中获取样本名称。但是,通过查看Wordpad中的文件,我发现样本名称被列出两次,第二次它有跟随它的日期戳(例如'Dibenzoylperoxid 120 C 03.05.1994 14:24:30')。在python中,我找不到这个字符串。我连自己都找不到时间戳。当我查看它应该发生的行时,我得到一堆随机字节。在记事本中打开看起来像python输出。

我怀疑这是一个编码问题。我已经尝试用Unicode读取文件,我已经尝试过读取行的片段并阅读它们,但我无法破解它。我很难过。

有关如何阅读此内容的任何想法,以便它解码正确吗?写字板是正确的(虽然现在随后尝试打开它,它看起来像记事本输出)。

谢谢!

编辑:

  • 我不知道是谁更改了标题,但当然它看起来像Python / Notepad中的随机字节。这主要是数据。
  • 这并不意味着是一个文本文件。我很幸运,Wordpad开场
  • 它没有被破坏。 DSC仪器程序读得很好。它只是专有的,所以我不知道它是如何滴答作响的。
  • 我尝试过使用'r','rb'和'U'标志。
  • 我使用utf8,16和32尝试了codecs.open,但它给出了UnicodeDecodeError:'utf8'编解码器无法解码位置49的字节0xdf:无效的连续字节。我不认为它有BOM,因为我认为它不是人类可读的。
  • 前32个字节(f.read(32))读取

    '\ x10 \ x00 \ x00 \ x00 \ x00 \ x00 \ x00 \ x00 \ x00 \ x00 \ x00 \ x00 \ x00 \ x00 \ x00 \ x00 \ x00 \ x00 \ x00 \ x00 \ x00 \ x00 \ x00 \ X00 \ X00 \ X00 \ X00 \ X04 \ X10 \ X00 \ X00'

    我对BOM没有太多了解,但是从阅读Wiki页面看,它看起来不像任何有效的UTF标记。

首次在Wordpad中自动解码时,文件的开头如下所示:           121 22二苯甲酰过氧化物120 C 03.05.1994 14:24:30 1 0 4096 ESTimeAI- @£®@nôÂ@49Õ@kÉå@FÞò@`sþ@N5A2A®“A”A-¥A¿A'AA“ÓAÿãAÅÅAäHA,œAÑÌAŸäA¤ ÆAE-AFNATöAÐ|AõAº^ A(ÄAèAýqA¹AÖûAº8A¬uAK«AgÜAüAÞAo4A将N AFAB

在记事本,Python和现在的Wordpad中打开文件的开头如下所示:  (空字节x00 ......)](x00 ...)eß(x00 ...)NvN(x00)......等

2 个答案:

答案 0 :(得分:4)

您的文件不是由ascii字符组成,而是由打开它的应用程序解释。如果你在wordpad中打开一个.jpg图像会发生同样的事情 - 你会得到一堆二进制和一些ascii字符,这些字符是人类可以打印和识别的。

这就是为什么你不能对你的时间戳进行纯文本搜索的原因。例如。

以下是代码中用于演示此问题的示例。在二进制文件中,您有以下字节:

\x44\x69\x62\x65\x6e\x7a\x6f\x79\x6c\x70\x65\x72\x6f\x78\x69\x64\x20\x31\
x32\x30\x20\x43\x20\x30\x33\x2e\x30\x35\x2e\x31\x39\x39\x34\x20\x31\x34\x3a\x32\
x34\x3a\x33\x30

如果要在像textpad这样的文本编辑器中打开它,它将呈现以下内容:

Dibenzoylperoxid 120 C 03.05.1994 14:24:30

以下是Python中的代码段:

>>> c='\x44\x69\x62\x65\x6e\x7a\x6f\x79\x6c\x70\x65\x72\x6f\x78\x69\x64\x20\x31\
x32\x30\x20\x43\x20\x30\x33\x2e\x30\x35\x2e\x31\x39\x39\x34\x20\x31\x34\x3a\x32\
x34\x3a\x33\x30'
>>> print c
Dibenzoylperoxid 120 C 03.05.1994 14:24:30

这些字节是十六进制格式,这就是为什么你不能用明文搜索它。

原因是因为二进制文件遵循一个非常特殊的结构(协议,规范),因此读取它的程序可以正确地解析它。如果你以jpeg图像为例,你会发现图像的第一个字节和最后一个字节总是相同的(取决于使用的格式) - FF D8将是jpeg的前两个字节, FF D9将是jpeg的最后两个字节,用于识别它。现在,图像编辑程序将知道如何开始将这个二进制数据解析为jpeg,并且它将会#34; walk&#34;文件内部的结构来渲染图像。 Here是指向资源的链接,可帮助您根据&#34;签名&#34;或&#34;标题&#34; - 文件10 00的前两个字节未显示在该数据库中,因此您可能正在处理专有格式,因此您无法轻松地在线查找规范。这就是逆向工程派上用场的地方。

我建议您在hexeditor中打开文件 - 它将为您提供十六进制输出以及ascii输出,以便您可以开始分析文件格式。我个人使用Hackman Hexeditor here(它是免费的,有很多功能)。

但是现在 - 给你一些有用的东西来搜索你感兴趣的数据文件是一种快速的方法,可以在开始搜索之前将搜索查询转换为二进制文件。

import struct

#binary_data = open("your_binary_file.bin","rb").read()

#your binary data would show up as a big string like this one when you .read()
binary_data = '\x44\x69\x62\x65\x6e\x7a\x6f\x79\x6c\x70\x65\x72\x6f\x78\x69\x64\x20\x31\
x32\x30\x20\x43\x20\x30\x33\x2e\x30\x35\x2e\x31\x39\x39\x34\x20\x31\x34\x3a\x32\
x34\x3a\x33\x30'

def search(text):

    #convert the text to binary first
    s = ""

    for c in text:
        s+=struct.pack("b", ord(c))

    results = binary_data.find(s)
    if results == -1:
        print "no results found"
    else:
        print "the string [%s] is found at position %s in the binary data"%(text, results)

search("Dibenzoylperoxid")

search("03.05.1994")

上述脚本的结果是:

the string [Dibenzoylperoxid] is found at position 0 in the binary data
the string [03.05.1994] is found at position 25 in the binary data 

这应该让你开始。

答案 1 :(得分:0)

是FutureMe。

您可能对写字板很幸运。我不确定,因为数据已经消失了,但是我猜想写字板做出了英勇的尝试,试图将文件解码为UTF-8(或者可能是UTF-16或CP1252)。该看来起作用的原因是,在大多数二进制协议中,字符串可能被编码为UTF-8,因此对于ASCII字符集,它们在转储中看起来相同。但是,其他所有内容都将进行二进制编码。

您对open(fn, 'rb')有一个正确的想法,但您应该只读了整个blob,而不是readlines,后者试图分裂成\n。由于db文件不是用\n分隔的,因此将无法正常工作。

本来更好的方法是对字节使用直方图,并尝试推断字段/行分隔符是什么(如果存在的话)。寻找TLV (type-length-value) encoded fields。由于您知道样本名称的列表,因此可以获取一个起始字符串的列表,使用它来查找斑点中的切点,并确定字段大小的规则性。

另外,购买比特币。