如何从硬盘的十六进制视图中确定 SQLite 数据库文件的结尾?

How can I determine the end of a SQLite db file from a hex view of the hard disk?

我的硬盘可能删除了其中的 SQLite 数据库文件。我正在读取磁盘字节并寻找 SQLite 文件的十六进制签名:53514c69746520666f726d6174203300

我的代码告诉我这些文件在磁盘上的偏移量,但我不知道它们的大小。

例如偏移量

是否可以从十六进制视图确定数据库的大小?据我所知,这些文件没有共同的结束字符。

我的代码

from pathlib import Path
import logging

file_sig = '53514c69746520666f726d6174203300'
disk = Path('/dev/sde1')  # sde is old HDD
try:
    with disk.open(mode="rb") as drive:
        for block_no in range(0, 488281250):
            byte = drive.read(512)
            hexx = byte.hex()

            try:
                idx = hexx.index(file_sig)
                byte_nos.append(idx + block_no * 512)
            except ValueError as e:
                logging.debug(e)
                pass
except KeyboardInterrupt:
    pass

with Path('./results.csv').open(mode='w') as f:
    for item in byte_nos:
        f.write("%s\n" % item)

感谢@Shawn,我发现 this 非常有用的 SQLite 数据库指南。

Beginning with SQLite version 3.7.1, a page size of 65536 bytes is supported. The value 65536 will not fit in a two-byte integer, so to specify a 65536-byte page size, the value is at offset 16 is 0x00 0x01.

我的数据库文件的开头如下所示:

53514C69746520666F726D617420330010000101004020200000CC9B0000032B000002E1
000000170000008000000002000000000000000000000001000000000000000000000000
00000000000000000000000000000000000000000000CC9B00

所以我 认为 我的页面大小是 0001 = 65536 字节,尽管这似乎是在偏移量 15 处(可能是从 0 到 1 计数的情况)。页数存储在偏移量 28 if...

the 4-byte change counter at offset 24 exactly matches the 4-byte version-valid-for number at offset 92

在我的例子中,更改计数器偏移量在这些偏移量处似乎是“00CC9B00”。因此,我将页数设为 0000032B,转换为大端 8 位值 43。

43 (page count) * 65536 (page size) = 2,818,048 bytes = 2.818048 MB

这与 Ubuntu 中的文件资源管理器告诉我的内容很接近,但它不正确。我知道我的测试数据库是 3,321,856 字节,所以我大约少了 503,808 字节。搜索文件时,我将只扩展我抓取的磁盘部分,因为我只是试图在原始文件中搜索某些文本,而不是将它们作为数据库加载。

文件大小可以通过查看十六进制的 header 来确定。

我将使用 forgetso 提供的错误答案中 header 的一部分来演示。我们只需要检查前 32 个字节,所以这是我们要看的部分:

53 51 4C 69 74 65 20 66
6F 72 6D 61 74 20 33 00
10 00 01 01 00 40 20 20
00 00 CC 9B 00 00 03 2B

前16个字节是文件类型标识符,所以我们真的只关心这部分来确定文件大小:

10 00 01 01 00 40 20 20
00 00 CC 9B 00 00 03 2B

上面粗体显示的两个字节部分(偏移量 16 和 17)将告诉我们数据库中包含的每个页面的大小。为了获得该数字,我们必须将大端十六进制表示形式转换为十进制形式。这可以使用十六进制到十进制的转换工具快速完成。

10 00

变成4096,也就是说每页是4096字节.

我们需要的另一部分是数据库中包含的页数。

10 00 01 01 00 40 20 20
00 00 CC 9B 00 00 03 2B

再看看上面的十六进制,现在加粗的四字节部分(偏移量28-32)就是我们需要确定总页数的部分。同样,我们只需要转换成十进制形式。

00 00 03 2B

变成811,也就是说有811页.

只需将这些值相乘即可计算出数据库文件的大小。

4096(bytes/page) * 811(pages) = 3321856    

因此,文件大小为 3,321,856 字节.
通过将此数字添加到 header 开始的偏移量可以找到文件的末尾。