2011-06-10

The Old New Thing: PEリソースは4バイトアラインにせよ。まあ、守らない奴もいるけど

PE resources must be 4-byte aligned, but that doesn't stop people from trying other alignments - The Old New Thing - Site Home - MSDN Blogs

PEヘッダー内のリソースは4の倍数のオフセットに格納されていなければならない。これは、アライメントに厳しい環境のためである。

まあ、どうせ守らない奴は守らないのだがね。第一、気を付けていれば、一応は動くしね。つまり、まあそりゃ、誰かx86じゃないWindows使ってる奴がリソース読み込んだら、クラッシュするだろうよ。でも、x86じゃないWindowsなんて誰が使ってんのさ? だろ?

Windows Vista SP1では、セキュリティ上の理由のため、リソースをパースするコードに、いくつかのチェックが加えられた。ここで重要なのは、リソースにアクセスする前に、正しくアラインされているかどうかを確かめるようになったのだ。これにより、アラインの正しくないリソースを読み込んだ場合のクラッシュを防げるようになった。プログラムが任意のバージョン情報のリソースを読み込むというのは、よくあることだ。例えば、エクスプローラーはファイルプロパティを見るときや、バージョン情報のコラムを有効にした時に、バージョン情報を読み込む。したがって、正しいリソースのアライメントを保証することは、リモートDoSアタックを防ぐことになるのだ。

そしたら、バグリポートがやってきた。「プログラムXYZがインストールできなくなった」。何故ならば、そのプログラムは自分自身のバージョン情報のリソースを読み込もうとして、失敗しているからだ。その理由は、プログラムをビルドするのに使ったツールが、4の倍数ではないオフセットにリソースを配置しているからである。「おいおい、マジかよ。よしてくれよ。そんな事すりゃ、3バイト無駄になっちまうだろうがよ。以前は、リソースアライメントしなくても動いたじゃん。だからそのまま出荷したんだよ」

別の例としては、あるゲームの追加パックがインストールできなくなった。何故ならば、ゲームのバージョン情報リソースを読み込むコードが動かなくなったからだ。

いくつかのプログラムが、「アプリ名は有効なWin32アプリケーションではありません」というエラーメッセージを表示して、実行をやめるようになった。これは、初期化の途中で、自分自身のバージョン情報リソースを読み込もうとして、ERROR_BAD_EXE_FORMATで失敗しているからだ。このエラーに対応するエラーメッセージをユーザーに表示しているのである。

修正としては、アライメントのチェックを以前と同じように緩くした。厳しいチェックは、アライメント要求が厳しいアーキテクチャのみで行うようにしたのだ。これは、あるマシンではリソースが読み込めるが、他のマシンでは読み込めないというプログラムの存在を許してしまう。しかし、アライメントが正しくないデータでも問題なく読み込めるという前提で書かれたプログラムをぶち壊すよりマシだ。

No comments: