📜  在 Linux 中使用幻数

📅  最后修改于: 2021-10-21 05:01:12             🧑  作者: Mango

本文旨在介绍幻数和文件头,如何基于幻数提取文件,以及如何在Linux环境中基于幻数破坏和修复文件。

幻数

幻数是文件的前几个字节,对于特定文件类型是唯一的。这些唯一的位称为幻数,有时也称为文件签名。

系统可以使用这些字节来“区分和识别不同的文件”,而无需文件扩展名。

在文件签名中定位幻数

大多数文件在文件开头的字节中具有签名,但某些文件系统甚至可能在开头以外的偏移量处具有文件签名。例如,文件系统 ext2/ext3 在第 1080 个和第 1081 个位置具有字节 0x53 和 0xEF。

  • 然而,有些文件没有幻数,例如纯文本文件,但可以通过检查字符集(文本文件的情况下为 ASCII)来识别。
    这可以通过使用以下命令来完成:
    file -i *name_of_file*
    
  • 幻数/文件签名通常对用户不可见,但可以通过使用十六进制编辑器或使用如下所述的“xxd”命令来查看。这些字节对于要打开的文件是必不可少的。
  • 更改/损坏这些字节将使文件无用,因为由于潜在的损坏,大多数工具将无法访问这些文件。
  • Linux reader中的file命令读取文件的幻数并根据幻数显示文件类型。
  • 例如,让我们以 PNG 文件为例。我们可以通过在 Linux 终端(本文使用的 kali Linux)中键入以下命令来查看文件的十六进制。此命令创建我们传递给它的文件的十六进制转储。
    xxd image.png | head
    

这会产生以下输出:-

在这张图片中,我们看到文件的第一组字节是

89 50 4e 47 0d 0a 1a 0a 
// magic number of PNG file

这些数字有助于系统识别正在使用的文件类型。一些没有用扩展名写入的文件,可以通过这些幻数来识别。

一个Zip 文件的例子,同样,在 zip 文件上使用上面提到的命令。

xxd test.zip | head

在上图中,我们可以看到文件以:

50 4b 03 04
// magic number of zip file

将一个文件附加到另一个文件并用幻数识别分区

我们可以使用Python来执行这个操作。本质上,我们将读取两个文件的字节,并将它们一个一个地写入另一个空文件。在本文中,我们将结合 PNG 和 Zip 文件。

"""
The first two lines open the two files to be read byte by byte
The third line opens an output file to be written to byte by byte
"""
  
input_file_1 = open("image.png", 'rb').read() 
input_file_2 = open("test.zip", 'rb').read()
output_file = open("output.png" , 'wb')
  
output_file.write(input_file_1)
output_file.write(input_file_2)

使用这个Python代码,我们获得了一个文件 output.png。在运行命令时:

xxd output.png | head

在这个文件中,我们注意到它以相同的 8950 4e47 0d0a 1a0a 十六进制开头。但是,如果我们运行命令

xxd output.png | grep "PK"

它将在十六进制中搜索 zip 文件的幻数(PK 是 50 4b 的 ASCII 等效值),
我们将得到以下输出:

在这张图片中,我们可以看到 zip 文件的幻数出现在 png 的十六进制中,这意味着我们已经成功地将 zip 文件的十六进制附加到了 png 的十六进制。下一步是将此 zip 文件与 png 分开。
有一个简单的实用程序 ‘binwalk’ 可以通过键入以下内容帮助我们轻松执行此任务:

binwalk -e output.png
-e stands for extract

如何使用幻数和偏移量从输出中提取 zip 文件:

  1. 找到要提取的文件的起始偏移量:在本例中,我们希望从 PNG 中提取 zip 文件。所以我们首先寻找ZIP头。如上图所示,我们执行命令’xxd output.png | grep“PK”’。在这张图片中,我们看到左列的偏移量。对于 zip 文件,偏移量为 00001c90。
  2. 从文件头开始的偏移量计算位数:我们现在必须计算从 zip 文件开始的偏移量的位数。我们可以手动计数并观察到它是 00001c95(每个十六进制值对应 1 位)
  3. 将此十六进制值转换为十进制:这可以通过打开一个Python IDLE 来完成(在 Linux 终端中键入“Python”。我们现在必须将此值转换为十进制。在Python IDLE 中,我们必须简单地将 0x 添加到在上一步中找到的值。
  4. 使用以下命令:
    'dd if=*input file* bs=1 skip=*value
    calculated in step 3* of=*output file name*'

    在上述命令中,“if”代表输入文件,“skip”表示到达我们希望提取的文件开头必须跳过的位数,“bs”表示字节数必须一次读取,“of”指的是输出文件名。
    参考下图,查看第3步和第4步的用法:

  5. 文件提取:我们现在可以从终端打开当前的工作目录,通过键入以下内容来查看我们提取的 zip 文件:
    nautilus ./
    

如何通过更改幻数来破坏文件?

更改文件的幻数会使文件无用。每当我们尝试打开具有扭曲标题的文件时,都会显示错误。

  1. 下载十六进制编辑器:要破坏文件,我们需要一个十六进制编辑器。 hexedit 是一种流行的工具。您可以使用以下方法安装它:
    sudo apt-get install hexedit
    

    您可以通过键入打开文件

    hexedit image.png
    

    你会看到这样的输出:

    使用十六进制编辑文件的十六进制

  2. 更改文件:要使用 hexedit 更改一个字节,您只需将光标移动到一个字节上,然后键入您想要的内容。为了这篇文章,我将把幻数从89 50 改为 00 00。
    要保存并退出,请按 ctrl X 然后按 Y。

损坏的魔法数字

在上图中,我们看到前2个字节已经变成了00 00,而在右边,我们可以看到文本从.PNG变成了..NG

如何修复幻数损坏的文件?

让我们使用上图中显示的示例,其中我损坏了 PNG 的前两个字节。如果您现在尝试打开 PNG,它会提示您“无法加载文件”,而不是“PNG”。这证明系统在打开文件之前查看幻数。知道 PNG 幻数以 89 50 开头,我们可以将字节改回其原始值。
让我们看另一个例子,使用 jpeg 图像。
让我们先看看一个工作的 jpeg 十六进制是什么样子的:

jpeg 幻数

原始幻数字节是

FF D8 FF E0

带有损坏的魔法字节的 JPEG 将如下所示:

损坏的 JPG

我们注意到这里的魔术字节是

EE A8 CC 00

因此,如果您尝试打开 jpg 文件,它将无法打开。我们得到这个错误:

图片错误

JPG 文件通常具有幻数“FFD8 DDE0”、“FFD8 FFDB”或“FFD8 FFE1”。
有了这些知识,我们所要做的就是尝试将这些组合作为文件的标题。这样做需要与文件损坏相同的过程。

    1. 打开十六进制编辑
    2. 通过将光标悬停并输入所需的值来更改前几个字节
    3. 保存(Ctrl X)并退出
    4. 尝试打开文件。如果文件未打开,请使用下一个可能的幻数重复步骤

将魔术字节更改为 FFD8 FFE0 后,图片会正常打开。