vmlinuz を解凍するための 1f 8b 08 00

2010 年 2 月 26 日 | カテゴリー: プログラム, 日記

vmlinuz.dump

お題「vmlinuz を解凍して vmlinux を取りだそう」。
環境は Mandriva Linux 2010.0。

Traditionally, when creating a bootable kernel image, the kernel is also compressed using the zlib algorithm, or since Linux 2.6.30[1], using LZMA or BZIP2, which requires a very small decompression stub to be included in the resulting image.

vmlinuz は gzip で圧縮されていることが知られています。Kernel 2.6.30 以降は LZMA か BZIP2 が使われていることもあるらしいですが、結論から言うと今回のは gzip。

ただし、ただの gzip 圧縮というわけではなく、16進数ダンプやらなにやらして確認して、ようやく解凍できました。

普通に gunzip を試みる

普通に gunzip を試してみます。

kei@frederica ~ $ gunzip /boot/vmlinuz-2.6.31.12-desktop-1mnb
gzip: /boot/vmlinuz-2.6.31.12-desktop-1mnb: unknown suffix -- ignored

gunzip は拡張子を見るプログラムだったみたいですよ。
拡張子をつけて改めて。

kei@frederica ~ $ cp /boot/vmlinuz-2.6.31.12-desktop-1mnb ./vmlinuz.gz
kei@frederica ~ $ gunzip ./vmlinuz.gz
 
gzip: ./vmlinuz.gz: not in gzip format

!? gzip じゃねーよとおこられます。
ちなみにこのあと、BZIP2 や LZMA を試しても同様に撃沈。

16進数ダンプして gzip ヘッダーを確認する

od (8進数ダンプツール) にオプションをつけて16進数出力して確認してみます。

od -A d -t x1 /boot/vmlinuz-2.6.31.12-desktop-1mnb  > vmlinuz.dump

-A d で表示されるオフセットの基数は10進数に。
-t x1 で16進数出力に。

gzip のヘッダーは「1f 8b 08 00」。なんか頭にいないんですけど。

0015952 c7 c1 c0 16 2c 00 48 c1 e9 03 fd f3 48 a5 fc 5e
0015968 48 8d 83 20 d8 2b 00 ff e0 1f 8b 08 00 d8 a0 5e
0015984 4b 02 03 ec fd 0b 7c 14 d5 fd f8 ff cf e6 02 41

ファイルに落として確認するのは面倒ですので、grep に渡すだけでいいです。

kei@frederica ~ $ od -A d -t x1 /boot/vmlinuz-2.6.31.12-desktop-1mnb | grep '1f 8b 08 00'
0015968 48 8d 83 20 d8 2b 00 ff e0 1f 8b 08 00 d8 a0 5e

gzip ヘッダーの開始バイト位置を確認する

0015968 48 8d 83 20 d8 2b 00 ff e0 1f 8b 08 00 d8 a0 5e

15968 から数えて 1f は 15968 + 9 = 15977。
つまりここまでスキップしてから gzip として解凍すれば、解凍できるはず。

dd でバイトスキップして zcat に渡す

dd でインプットファイルに /boot/vmlinuz-2.6.31.12-desktop-1mnb を食べさせて、ブロックサイズを1で 15977 個スキップします (0 から数えるから)。

kei@frederica ~ $ dd if=/boot/vmlinuz-2.6.31.12-desktop-1mnb bs=1 skip=15977 | zcat > vmlinux
 
gzip: stdin: decompression OK, trailing garbage ignored

「decompression OK」!

strings で vmlinux を参照

無事解凍できましたが、当然バイナリ。
でも、Kernel version とかの文字列が含まれているはずです。

kei@frederica ~ $ strings vmlinux | grep "Linux version"
Linux version 2.6.31.12-desktop-1mnb (qateam@titan.mandriva.com) (gcc version 4.4.1 (GCC) ) #1 SMP Tue Jan 26 02:59:07 EST 2010

とれたー!

結論

vmlinuz は gzip ヘッダーが頭にいないので、dd でスキップして解凍しましょう。
ちなみに fedora 8 の xen kernel は拡張子を .gz にしたうえで gunzip したら普通に解凍できたり。xen kernel は単純な gzip なのかなー。

  1. mayn_lum
    2010 年 2 月 26 日 11:17

    odして目的の文字列が同じ行にあったのでgrepで見つかりましたが、

    もし2行にわたっていたら上の方法では見つけられないので、もう一工夫必要がありますね。

  2. kei
    2010 年 2 月 27 日 00:13

    ですねー。

    まあ今回は od でとりあえずってかんじですけど、自前でダンプ+位置の確認をするスクリプトを書けば問題ない気もするので、スクリプト書いて「vmlinuz 解凍ソフトウェア」という名目で公開するとかアリかも。

    解凍の需要があるのかって話からですね、はい。