WindowsのThumbs.dbはOLE Compound DocumentとかStructured Storageという形式でできている。Wordのdocファイルにも使われていて、要はアーカイブの一種らしい。
この形式を解凍する方法自体はメモしない。ここでは内部にどういうファイルが入っているかだけ書く。
これを読み込むライブラリは、Rubyではruby-oleジェム、PerlならWin32::OLE、JavaならApache POIのPOIFS、CならCOMのIStorageとかPOLEというライブラリがある。
ディレクトリの内容
そのたぐいのライブラリで解凍すると、中身のディレクトリはこうなっている。フォルダはなく、いくつかバイナリファイルが入っているだけ。
- Catalog
- 01
- 1
- 11
- 2
- 21
- 3
- 4
- 5
- ...
内容としては、名前が数字のファイルがJPEGファイルにヘッダがくっついたもので、Catalogにその数字と実ファイル名の対応付けが記録されている。
各サムネイルにはIDがついている。
不思議なのはIDとファイル名が文字列として反転しているというところ。
idが5のサムネイルは5というファイルに入っているが、idが13のサムネイルは31というファイルに入る。
カタログ (Catalog ファイル)
Catalogのフォーマットは先頭からこう。数値は全てUint32LE。
- ヘッダが16バイト
- 4バイト~8バイト目にサムネイル数
- サムネイル数だけ以下を繰り返し(各エントリのサイズは不定)
- エントリ全体のサイズ
- ID
- 更新日時
- 何かの数値
- UTF16LEでファイル名
- 0でパディング
サムネイル (0, 1, 11, 2, 21 ..)
サムネイル画像のファイルの内容は以下のとおり。
- ヘッダ (12バイトか16バイト)
- JPEGファイル
ヘッダの長さは可変というか、12バイトか16バイトかのどちらからしい。
本来ならヘッダにあるタイプを調べるべきなのだろうが、とりあえずJPEGファイルの頭にあるマジックナンバー(0xFF 0xD8)を目印にすればヘッダの内容を読む必要はない。
実装
画像を吐き出すだけのツールを作るなら、流れはこうなる。
- Structured Storageのライブラリを使ってthumbs.dbを読み込む
- Catalogファイルを取り出して上のフォーマットで解釈する
- 各ファイル名についてサムネイルを取り出し、JPEGファイルをその辺に書き出す
これをRubyとC++で書いた。
手抜き
以上はlibforensicsというPythonのライブラリのlf.win.shell.thumbsdbのコードを読んだだけなので、このライブラリを使うのが一番早いかもしれない。
こういった解体処理をする必要があるのは元のファイル名が欲しいときだけで、サムネイル画像を取り出したいだけならまじめに読み込む必要はない。
無圧縮で暗号化もされていないので、thumbs.dbを普通に開き、JPEGのSOI(0xFF 0xD8)とEOI(0xFF 0xD9)を探して次々書き出せばすむ。
(copied from tumblr)