実行可能ファイルのシンボル情報を削除して情報漏えいのリスクを下げる方法を説明します。
業務などでC/C++言語で作ったプログラム(実行可能ファイル)をリリースしたり他の人に渡すことがあると思います。 そのときにシンボル情報というものに気をつけていますでしょうか? シンボル情報というのは関数名とか変数名などの情報です。
例えばデバッガなんかで変数の値をのぞいたり、特定の関数まで実行したりできますよね。 それは実行可能ファイルにシンボル情報があるからできるわけです。どこにどんな変数や関数があるかラベルづけされているわけですね。 このように実行可能ファイルにはシンボル情報が含まれているんですが、場合によってはこれが情報漏洩の原因になりかねません。
デバッグ用の関数や変数や隠し機能などが漏れてしまう可能性があります。また、ビルドしたときのパス情報なども含まれるためにユーザ名なんかもわかってしまうかもです。 そこで今回は、実行可能ファイルからシンボル情報をみる方法を示したうえで、それを削除する方法を示します。
Caution
ライブラリ(.a, .so)やオブジェクトファイル(.o)からシンボル情報を削除すると、 リンクできなくなってしまうので要注意です! リンカはシンボル情報を参照してそれらを結合するので消してはダメです!
シンボル情報をのぞいてみよう
シンボル情報を見るには nm コマンドを使用します。今回の例はWindows MINGW上で実行していますが、Linuxでも同様です。
ためしに自前でビルドした実行可能ファイルに対してnmを実行したところ、下記のようになりました。
左の数字はアドレス、真ん中はデータの種類、右はシンボル名です。なんとなくたくさんのデータや関数があるんだなぁ、というのがわかるかなと思います。
このように、nmでシンボル情報を表示することで、関数名やファイル名が簡単に見ることができてしまいます。
| |
さらに実行可能ファイルの中身をのぞいてみよう
nmでもいろいろな情報が見ることができますが、さらにもっと情報が見れないか試してみましょう。
そういう時はstringsというコマンドが便利です。これは指定したファイルから4文字以上の繋がったASCII文字を抽出するコマンドです。
つまりバイナリファイルから4文字以上のASCII文字を片っ端から表示するわけですね。 こんな感じにひたすらにASCII文字が表示されていきます。
| |
例えばビルドした人を知りたければ、stringsの結果をgrepに渡してあげればわかる可能性があります。
下記の例はMINGW(Windows)なのでパスの形式がC:で始まっています。Linuxの場合は適宜そこを置き換えてください。
C:\Users\username\work\tmp\ccache-3.5というようにビルドしたときのパスがあります。usernameのところでユーザ名が判別できてしまいます。
| |
このようにして、割と簡単にいろんな情報を抜き出せてしまいます。悪用できてしまいそうですね。
シンボル情報を削除する
ではどう対処すればいいか。不要なシンボル情報を削除すればOKですね。stripというコマンドがそれを実現してくれます。
使い方も簡単。単に実行可能ファイルを渡せばいいだけです。
| |
こうするとnmコマンドを実行しても下記のように「シンボルが見つかりません」という旨のメッセージが表示されます。シンボル情報の削除に成功していますね。
| |
stringsについては、さすがにすべてのASCII文字を削除するわけにはいかないので、多少は残ります。
例えばprintfで表示するメッセージなんか削除されたら困りますし。ですが、先ほどみたようなビルドパスは削除されます。
| |
これで余計なシンボル情報が削除できていることが確認できましたね。
まとめ
今回は実行可能ファイルに含まれているシンボル情報による漏洩の危険性と、その削除の仕方について述べました。 上記は基本的な使い方のみの紹介ですので、興味のある方はGNUのマニュアルなどを参照していろいろと遊んでみてください!