バイナリファイルの一部をバイト数指定で切り出す方法

バイナリファイルの一部を切り出したい時があると思う。
今はなくてもいつかはほしいと思うだろう。

例えば、そうパケットキャプチャで、httpのトレースをしていたときに
途中から生でデータを取ったら、HTTPヘッダ(テキスト)とかついてきて、その後にバイナリになることがある。

これをテキストエディタで編集していくと絶対バイナリが壊れる。
だからバイナリとして切り出す必要がある。

今回はLinuxのコマンドで簡単にやってみる。

バイナリの中身を見てみよう

以前このブログでも書いた、ランダムなバイト列のファイルを作る技でバイナリを作った。
それで真ん中にテキストを入れて結合してみた。

それをhogeというファイルにした。

hexdumpでCのオプションをつけると、16進数表記で隣にASCII表示でバイナリの中身が見える。

真ん中ぐらいに hello worldがあるのが分かるだろう。

これをテキスト部分だけ抜き出してみよう。
0x20はスペースなので、helloの前にに2つスペースがある。
0x0aはLF改行なので、worldの後にスペース2つの改行があるという感じだ。

では、何バイト目から何バイト目までを切り取るか見てみよう。

0x20は00000040と書かれた行の先頭からあるので、
0x41バイト目から始まっている。
1行につき16バイト 0x10バイトまで書かれているのだ。
だから40と書かれていたら0x41から始まる行である。

その行の最後までがテキストなので、0x50バイトまでだ。
ちょうど16バイト分なのだ。スペースと改行を含めて考えれば16文字分あった。

0x40は10進数にすると64。
つまりファイルの先頭からテキスト部分まで64バイトだ。

ファイルの後半は0x50 から 0x80まであるので、これも数えてみると0x40バイト分あるので、後半も64バイトだ。

つまり最初の64バイトが不要で、16バイトが必要で、その後の64バイトが不要ということになる。

ddコマンドで切り取り

ddコマンドを知っているか?
LinuxのOSイメージを取ってきたら、USBメモリなどに書き込んだりするときに使うだろう。
バイトをそのままあるファイルやデバイスから、別のファイルやデバイスに書き込むコマンドだ。
だから、SDカードやUSBメモリなどのバックアップなどにも使っている。

でもこれはバイナリを上手く扱えるコマンドという側面がある。

ddコマンドは入力ファイルと出力ファイルを取り違えると、ファイル破損してしまうので気をつけること。
出来ることならばまずファイルをコピーしてバックアップしておくと良い。

単刀直入にまずコマンドを示す

dd if=./hoge of=./hello bs=1 skip=64 count=16

ifが読み込むファイル。つまり元ファイル。
ofが書き込むファイル。つまり新たに保存されるファイル。
これを間違えると元のファイルが無くなってしまう。

bsは書き込む単位
例では1バイト単位にしている。

skipは元ファイルを読み込む際に何ブロックを読み飛ばすかという意味になっている。
つまり例では64ブロックを読み飛ばしている。
このブロックはbsで指定したバイト数になっている。
bsが今回1バイトなので64バイトを先頭から読み飛ばしている。
たとえばbs=2だったら32と書くことで、64バイトを読み飛ばしてくれる。

読み飛ばすとは、つまり元のファイルの65バイト目からコピーを開始するということ。

countはコピー開始から何ブロック分コピーをするかという意味で
これもbsで指定したバイト数に依存しているので、例では16バイト分コピーするという意味になっている。
bs=2と指定したら、count=8と書くことで、16バイト分切り出すことができる。

結果はこのようになった。
テキスト部分のみ正しく抜き取れた。

 

ちょうど16バイト分切り取れていることが確認できる。

まとめ

大きめのファイルだと、数えるのがむずかしいかもしれないが、
何バイト目から何バイト分切り出す必要があるのかが確認できれば、あとは簡単に切り取ることができる。

古めのシステムで使われている固定長のファイルなどはこの手の計算がしやすい。
シェルでループで回せば、他の言語より手軽に分割することができる。

スポンサードリンク

関連コンテンツ