はじめに
こんにちは!ミルディアの藤井です。
突然ですが、「知らない拡張子のファイル、なにで開く?」この問いになんて答えますか?
当然こう答えますよね、せーの、「バイナリエディタ!」
バイナリエディタとは?
ファイルの行きつくところ、テキストファイルも画像ファイルも、すべて 0100101… 2進数の世界です。これを直接見れてしまうのが、バイナリエディタです。
これを直接読めてしまう人はごくごく少数の方ですので、バイナリエディタでは読みやすいようにいろいろな工夫がなされています。
バイナリエディタに求めるもの
編集、検索機能
これができなきゃエディタじゃありません。
ASCII 表示機能
テキストファイルだった場合にすぐわかるように、 ASCII コードだったらそのように表示する機能。たいていのバイナリエディタにはついています。
マルチバイト文字対応
少なくとも Shift JIS 、UTF-8 には対応していてほしいですよね。
ディスアセンブル機能
これは素直にディスアセンブラを使いましょう。
フォーマットデコード機能
テキストファイルではない場合(XMLファイルやCSVファイルはテキストファイルのなかまです)、ファイルは特定のフォーマットで2進数が並んでいます。ただ、人間が直接読むのはとてもむつかしいので、フォーマットにしたがって読んだ結果を表示してくれる機能がついているバイナリエディタがあります。
このフォーマットデコード機能について、本稿では取り上げていきます。
フォーマットデコード機能の例
ここまででぴんと来ていない方へ、例をあげて説明します。
Windows を使う方ならおなじみ、画像ファイルのBMP形式について説明します。
下図はBMPファイルの先頭を読んで、16進数で表示したものです。
左端の赤地のところは何行目か示すものですので、実際のデータは青地のところを見てくださいね。
先頭2バイトは文字「BM」の文字コード、「42」「4D」が入っています。BMPファイルだよ、という主張です。
途中は端折って、2行目には「A7 06 00 00」「7E 01 00 00」とありますね。これは画像の幅と高さです。「A7 06 00 00」は10進数で表すと 1703、「7E 01 00 00」は 382 です。
これで、画像の幅と高さがわかりました。
めんどくさいですね。
これがフォーマットデコード機能がついているバイナリエディタなら、一目でわかります。素晴らしいです。
余談:エンディアン
余談ですが、「A7 06 00 00」を10進数で表したとき、なぜ 1703 になるのでしょうか?
手元の電卓で10進数に直してみましょう。
あれ、1703 になりませんね。
1703 を16進数で表すと、「6 A7」です。また、BMP画像の幅の格納領域は32ビット=4バイト=16進数で8桁なので、上の桁は0で埋めて「00 00 06 A7」と表現するはずです。
それが「A7 06 00 00」と格納されています。逆ですね。
実は、Windows を動かしているCPU、Intel 系のCPUは、逆から読むのが好きなのです。つまり、「00 00 06 A7」を 「A7 06 00 00」とひっくり返した方が、Intel CPUは読みやすいのです。
なので、BMPファイルは「A7 06 00 00」とひっくり返った順序で格納されているのです。
ちなみに、ひっくり返った順序で格納する方式を「リトルエンディアン(小さい位から書く)」、普通に格納するのを「ビッグエンディアン(大きい位から書く)」と呼び、どっちで格納するかのことを「バイトオーダー」「エンディアン」などと呼びます。
フォーマットデコード機能のついたバイナリエディタ
横道にそれました。ここでは、フォーマットデコード機能のついた、つぎの2つのバイナリエディタを紹介します。
- TSXBIN
- ImHex
TSXBIN
TSXBINは、Windows ネイティブアプリです。対応OSは Windows10 までとなっていますが、Windows 11 でも問題なく動作します。
https://www.net3-tv.net/~m-tsuchy/tsuchy/tsxbin.htm
現代では XML 形式のデータが多いためデータファイルはテキストエディタで読めて便利ですが、昔はデータサイズを小さくするために独自形式のバイナリファイルがほとんどでした。
ですので、フォーマットデコードできるこのエディタがあると知って、当時飛びつきました。それまでは、形式ごとに ローダーを書いたりデバッガで見たりして大変でした。
デフォルトで対応している拡張子
オフィシャルで配布されているシンボルファイルは下記の通りです。Windows 開発には十分です。
https://www.net3-tv.net/~m-tsuchy/tsuchy/tsxmacro.htm
良い点
これはなんといってもみんなが使っているので、良い意味で枯れているところです。筆者的には、使い慣れているというメリットもあります。
エンディアン選択などデータファイルを読むために必要な機能がひととおりそろっています。
いまいちな点
歴史あるソフトなので仕方がないのですが、下記がいまいちです。2016年以降更新されていないようなので、改善も期待薄です。
- ある程度大きなファイルになると閲覧のみとなり、編集できなくなる。
- 対応している文字コードが Shift-JIS とUnicode(UTF-16)のみ。
- ドキュメントが.HLP 形式なので、Windows 11 では読めない。
ImHex
TSXBIN は良いソフトなのですが、なにしろ時代を感じるので乗り換え先を探していたところ、めぐり逢ったのが ImHex です。
各種OSに対応しており、Web 上でも試せます(Web 上だと肝心のパターンファイルが動かなかったりしますが…)。
TSXBINでは切り替えて表示していたバイナリ表示部分とフォーマット表示部分が同時に見られるなど、マルチウィンドウが便利です。
以下はざっと触ってみての感想です。なにしろ機能が多すぎてまだまだつかみ切れていません。
デフォルトで対応している拡張子
オフィシャルで配布されているパターンファイルは下記の通りです。知らないファイル形式がいっぱい…。
https://github.com/WerWolv/ImHex-Patterns/tree/master/patterns
良い点
なんといっても、ソースが公開されているので、困ったら対応できる点です。そのほか特徴的な点は次の通り。
- 大きいファイルも編集可能。操作も軽い。
- 文字コードがテーブルになっているので、自分で作れる(はず)。
いまいちな点
日々開発がすすんでいるため、明日には解決しているかもしれません。
- DELキーでサクサク削除できない。
- 拡張子でフォーマットを自動判断してくれない。
- まだちょっと不安定なところがある。フォントを変えると落ちたりする。
解析用ファイル
今回紹介したどちらのバイナリエディタも、スクリプトを用いた解析用ファイル(TSXBIN:シンボルファイル、ImHex:パターンファイルと呼ばれます)を使用してフォーマットを定義します。スクリプトはどちらもC言語ライクで、C/C++言語が書けるなら問題なく書けます。
尻込みする必要はありません。スクリプトのドキュメントを読まなくても、既存の解析用ファイルを拡張していけば簡単です。
例えば ImHex のパターンファイルはこんな感じです。
#pragma description OS2/Windows Bitmap
#pragma MIME image/bmp
#pragma endian little
import std.mem;
struct BitmapFileHeader {
u8 bfType[2];
u32 bfSize;
u16 bfReserved1;
u16 bfReserved2;
u32 bfOffBits;
};
(中略)
struct BitmapInfoHeaderV1 {
u32 biSize;
s32 biWidth;
s32 biHeight;
u16 biPlanes;
u16 biBitCount;
Compression biCompression;
u32 biSizeImage;
s32 biXPelsPerMeter;
s32 biYPelsPerMeter;
u32 biClrUsed;
u32 biClrImportant;
};
(中略)
struct Bitmap {
u8 data[std::mem::size()] [[no_unique_address, hidden]];
BitmapFileHeader bmfh;
// Deduce the header version from its size
u32 bmInfoHeaderSize [[hidden, no_unique_address]];
match (bmInfoHeaderSize) {
(40): BitmapInfoHeaderV1 bmih;
(52): BitmapInfoHeaderV2 bmih;
(56): BitmapInfoHeaderV3 bmih;
(108): BitmapInfoHeaderV4 bmih;
(124): BitmapInfoHeaderV5 bmih;
(): BitmapInfoHeaderV1 bmih;
}
padding[bmih.biSize - sizeof(bmih)];
if (bmih.biBitCount <= 8)
{
if (bmih.biClrUsed > 0 )
Colors rgbq[bmih.biClrUsed];
else
Colors rgbq[1 << bmih.biBitCount];
}
if (bmih.biSizeImage > 0 )
u8 lineData[bmih.biSizeImage];
else
u8 lineData[bmfh.bfSize - $];
} [[hex::visualize("image", this.data)]];
Bitmap bitmap @ 0x00;
C言語のヘッダみたいですね。構造体を記述すればよいので、まさにヘッダファイルからそのままコピーしてくることができます。
まとめ
以上、フォーマットデコード機能を持つ2つのバイナリエディタを紹介しました。
バイナリデータファイルを扱う人には必須ともいえるこれらのツール。
おもしろそう、と興味を抱いた方は、画像ファイルや音声ファイルをちょっとのぞいてみませんか?