缘由

前一段时间微软的地平线5 Steam版本打折,于是就想着把之前的微软商店版本的存档给转移过来。于是在网上找到了对应的转移方法,找到了存档位置一打开,微软的存档文件大概是这样的:

Alt text

全都是十六进制的文件名以及完全没有文件名后缀标识这是个什么文件,找的人那叫一个头疼。

同时在以前的 CTF 中也曾经遇到过此类需求。

于是,有了编写一个批量检测文件头的功能的想法,说做就做,开始思考需要哪些功能组件。

思考

功能其实并不复杂,原理就是读取文件二进制的前X位,然后根据某个表对照判断出这个文件可能的类型。与文本匹配功能有点类似,只不过是改为对二进制操作。

Alt text

比如这是一张PNG的图片,使用二进制编辑器打开后会发现PNG的图片最开始的几位都是是一样的,用这个符号位操作系统可以来判断打开文件的类型。

首先分解下需要的功能

  • 读取文件 / 批量读取文件 / 按照选择文件夹批量读取文件
  • 提取文件头部 X 位的二进制
  • 二进制转换十六进制
  • 加载头文件对应表
  • 使用头文件对应表匹配头文件

这么看需求并不复杂,再来分析下 GUI 部分

input:

  • 文件选择器
  • 头文件对应表选择器(默认使用内置)

output:

  • 输出结果面板(预定使用弹出式新窗口)
  • 一键重命名为对应后缀按钮
  • 导出结果按钮

info:

  • 标题
  • 展示已选择的文件名称 / 数量
  • 展示选择的头文件表名称 / 条目数量
  • 提示正在检测的进度条

control:

  • 开始检查文件头按钮

简单设计下用来匹配的 JSON 文件格式:

{
  "FFD8FF": { // 文件头十六进制表示作为 key
    "ExtensionName": "JPG", // 文件尾缀名
    "FileHeaderHEX": "FFD8FF", // 文件头十六进制
    "FileDescription": "JPG Graphic File" // 文件类型的简单描述
  },
  "89504E": {
    "ExtensionName": "PNG",
    "FileHeaderHEX": "89504E",
    "FileDescription": "PNG Image File"
  }
}

目前先考虑这么多吧,之后有新想法再添加。

实现

程序已经编写完成,使用读取文件固定位数的头部二进制来进行匹配,需要使用默认或自定义的头文件表。输出面板支持一键重命名与导出结果。

Alt text

首先最上方还是一如既往的使用英文标题,但在左侧列表树显示为文件头检测。

标题下方设计为规则加载模块,最左边是一个切换模式的按钮,默认为 默认模式 ,使用程序内自带的默认文件头JSON文件,这个JSON文件会在程序打开文件头检测功能的时候保存一份到程序的配置路径。

点击“使用默认文件头JSON” 这几个字可以使用系统默认软件打开这个JSON文件。

最右边是显示JSON文件内文件头信息的数量

Alt text

点击切换按钮可以切换为自定义模式,同时选取要使用的JSON文件加载。

Alt text

加载完后中间会显示已加载的JSON文件的名称,点击即可使用系统的默认软件打开这个JSON文件,最右边也会显示为已加载JSON内文件头信息的数量。

再往下的控件作用分别是:显示已经选取的文件数量,检查文件头HEX的数量 默认检查文件头开始的3个HEX字符,以及检查按钮,点击可以对选择的文件进行文件头检查。

再下方是一个加载文件的按钮,点击可以选取要检查的文件,可以多选但不能选取文件夹。选取完成后按钮会缩小到右下方,原本按钮位置会显示已经选取的所有文件路径,一个一行。

Alt text

加载完文件后点击检查按钮进行检查,完成后弹出结果页面,如下:

Alt text

结果页面是一个列表,展示一些基本信息,可以双击单条目标使用系统默认程序打开。

在匹配到的情况下,扩展名列会显示 UNKNOWN ,文件类型详情页会显示 NULL

右下方有两个操作按钮,导出会以CSV的格式导出整个结果列表,重命名按钮会将所有除了扩展名为UNKNOWN的文件在末尾加上扩展名,如果有多个扩展名的情况下会优先使用处于;最前面的一个。

总结

实现了一个比较早就有初期想法的功能,果然开发和想法的实现还是需要时间。只有在工作不怎么忙的时候才能有这种闲心。

虽说是用来匹配文件头,但本质上是从头读取二进制,用来写一些自定义规则匹配的东西说不定也可以。

嗯,接下来一段时间又要忙起来了,不懂什么时候能进行下一个功能的开发了。