前の日 / 次の日 / 最新

swk's log

2007-10-27 Sat

* ELF ファイルが Linux のものであるか否かを知る方法 [tech] 1 user

【追記】さらにその後,「『7f454c46 01010100 00000000 00000000』の時 点でelfファイルであることは判るが,Linuxで作られたかは0x0114バイトは 見ないと判らないはず,この人は『バイナリ萌え』ではない!」との突っ込 みを頂きました.

Robot.Mとの優雅な平日:バイナリ萌え,再び・・・

0xcafebabe の話を知った大学生の頃,危うくバイナリ萌えの暗黒面に落ち そうになったものの,軽うじて生還して今は普通人として暮らしています.


というわけでバイナリ萌えでない私にとっては,上の「Linuxで作られたか は0x0114バイトは見ないと判らない」はすごく不思議だった.だって ELF って 8 バイト目に OS/ABI あるじゃん.で,ELFOSABI_LINUX (= 0x03) っ て定義されてるじゃん.そこ見ればいいんじゃないの?

…と思って手近にあった Vine Linux に転がっているバイナリを調べてみる と,8 バイト目は軒並 0x00 なのであった.0x00 は ELFOSABI_NONE であり ELFOSABI_SYSV である.で,確かに readelf すると

% readelf -a /bin/ls | grep OS/ABI
  OS/ABI:                            UNIX - System V

と表示されるのであった.むー.

さてそれではどうやって Linux のものだと判定すればよいのか,そしてそ れはなぜ「0x0114バイトは見ないと判らない」のか,ちょっと調べてみるこ とにした.

調べたのは file コマンド.

% file /bin/ls
/bin/ls: ELF 32-bit LSB executable, Intel 80386, version 1, for GNU/Linux 2.2.5, dynamically linked (uses shared libs), stripped

てな感じで Linux だと判定してくれるので,きっと何か手がかりがあるだ ろう.

というわけで FreeBSD の /usr/src/contrib/file/readelf.c あたりを 眺めてみると,donote() の中で判定しているようだ.ELF のプログラムヘッ ダのうち NOTE タイプのものを探して,その先頭 Elf32_Nhdr サイズ分 (た だし 32 ビット ELF の場合.定義は file/readelf.h の中で,実際のサイ ズは 12 バイト) スキップしたところに 'G', 'N', 'U', '\0' という 4 バ イトがあることを確認し,その次の 1 バイトを調べている.そこが 0x00 だったら GNU/Linux であるという判定をしているようだ.ちなみにそこに 出てくる値としては

#define GNU_OS_LINUX    0
#define GNU_OS_HURD     1
#define GNU_OS_SOLARIS  2

が定義されている.ちょwww HURD って単語久々にみたわwwwwwwwww

NOTE タイプのプログラムヘッダがどこにあるかというと,

% readelf -a /bin/ls
(略)
Program Headers:
  Type           Offset   VirtAddr   PhysAddr   FileSiz MemSiz  Flg Align
(略)
  NOTE           0x000108 0x08048108 0x08048108 0x00020 0x00020 R   0x4
(略)

てな感じになっていて,先頭からのオフセット 0x108 バイトのところから 始まるらしい.ここから Elf32_Nhdr 分の 12 バイト進んだ 0x114 の,さ らに 'G', 'N', 'U', '\0' の分の 4 バイト進んだところ,つまりオフセッ ト 0x118 バイトのところを見るとようやく Linux かどうかがわかる,とい う仕組みのようだ.実際に見てみると,

% hexdump -c /bin/ls | grep ^0000110
0000110 001  \0  \0  \0   G   N   U  \0  \0  \0  \0  \0 002  \0  \0  \0

となる.うーん,なるほど.

ついでに書いとくと,NOTE タイプのプログラムヘッダは必ずしも 0x108 か ら始まるわけじゃなくて,例えば /bin/rpm なんかは

  NOTE           0x000094 0x08048094 0x08048094 0x00020 0x00020 R   0x4

なのであった.つまりオフセット 0xa4 (= 0x94 + 12 + 4) を見る必要があ るってことでいいかな?

% hexdump -c /bin/rpm | grep ^00000a0
00000a0   G   N   U  \0  \0  \0  \0  \0 002  \0  \0  \0 002  \0  \0  \0

よさげである.

というわけで,どうやら「Linuxで作られたかは0x0114バイトは見ないと判 らないはず,この人は『バイナリ萌え』ではない!」という突っ込みもバイ ナリ萌えとしてはまだツメが甘いようです.うーむ,バイナリアン恐るべし. ついて行けん.


で,最初の話に戻るんですが,これらのファイルってどうして OS/ABI に ELFOSABI_LINUX を使わないんでしょう? 逆に言うと ELFOSABI_LINUX って どういうときに使われてるんでしょう? 教えて偉い人.

[ コメントを全部見る / コメントを書く] [ TrackBack ( )] [固定リンク]

* [baby touch] 『あまり使われないのは、システムコールとかの"実装"に依存し... (2007-11-06 21:15:48)

<< 2007-10 >>
SuMoTuWeThFrSa
123456
78910111213
14151617181920
21222324252627
28293031

2008 : 01 02 03 04 05 06 07 08 09 10 11 12
2007 : 01 02 03 04 05 06 07 08 09 10 11 12
2006 : 01 02 03 04 05 06 07 08 09 10 11 12
2005 : 01 02 03 04 05 06 07 08 09 10 11 12
2004 : 01 02 03 04 05 06 07 08 09 10 11 12
2003 : 01 02 03 04 05 06 07 08 09 10 11 12
2002 : 01 02 03 04 05 06 07 08 09 10 11 12
2001 : 01 02 03 04 05 06 07 08 09 10 11 12
2000 : 01 02 03 04 05 06 07 08 09 10 11 12
1999 : 01 02 03 04 05 06 07 08 09 10 11 12
1998 : 01 02 03 04 05 06 07 08 09 10 11 12
1997 : 01 02 03 04 05 06 07 08 09 10 11 12
1996 : 01 02 03 04 05 06 07 08 09 10 11 12

最終更新時間: 2008-04-23 08:31


Shingo W. Kagami - swk(at)kagami.org