\r\n\r\n
Linuxのfileコマンドは、そのファイルの種類をすぐに教えてくれます。バイナリファイルであれば、その詳細を確認することができます。分析に役立つファイルが揃っています。これらのツールの使い方を紹介します。
ファイルは通常、パッケージがそのファイルの種類とその中のデータが何を表しているかを識別できるように、いくつかの特性を持っています。PNGファイルをMP3音楽プレーヤーで開いても意味がないので、ファイルに何らかのIDを持たせることは有用かつ実用的である。
これは、ファイルの先頭にある数個のシグネチャバイトである可能性があります。これにより、ファイルの形式と内容を指定することができます。ファイルアーキテクチャと呼ばれる、データ自体の内部組織のユニークな側面からファイルタイプが推測されることもあります。
Windowsなどの一部のOSでは、ファイル拡張子によってすべてがガイドされます。Windowsは、拡張子がDOCXのファイルは、実際にDOCXのワープロファイルであると思い込んでいます。 Linuxは、すぐにわかるように、そのようなことはありません。それは証拠を必要とし、ファイルの中から探します。
ここで紹介するツールは、この記事の調査に使用したmanjaro20、fedora21、ubuntu20.04のディストリビューションに既にインストールされています。それでは、fileコマンドで調査を開始します。
カレントディレクトリには、ドキュメント、ソースコード、実行ファイル、テキストファイルなど、さまざまな種類のファイルが混在しています。
lsコマンドはディレクトリの内容を表示し、-hl(human readable size, long list)オプションは各ファイルのサイズを表示します。
ls -hlこれらのファイルを試し、何が得られるか見てみましょう。
file build_instructi***.odt file build_instructi***.pdf file COBOL_Report_Apr60.djvu3つのファイル形式は正しく認識されていた。可能であれば、文書からより多くの情報を得ることができた。
ODTファイルの拡張子を任意の値XYZに変更しても、ファイルブラウザやfileを使ったコマンドラインでは正しく認識されます。
ファイルブラウザでは、正しいアイコンが表示されます。コマンドラインでは、fileは拡張子を無視し、ファイルの内部を調べてそのタイプを判断します。
file build_instructi***.xyzメディア上のファイル(画像や音楽ファイルなど)を使用すると、通常、そのフォーマット、エンコーディング、解像度などの情報が発生します。
file screenshot.png file screenshot.jpg file Pachelbel_Canon_In_D.mp3興味深いことに、プレーンテキストファイルであっても、fileは拡張子でファイルを判断しない。例えば、拡張子が「.c」で、ソースコードではなく標準的なプレーンテキストを含むファイルがあった場合、それを本物のcのソースコード・ファイルと勘違いすることはありません:。
file function+headers.h file makefile file hello.cこのファイルは、ヘッダーファイル(".h")をファイルのCソースコード集の一部として正しく識別し、makefileがスクリプトであることを認識しています。
バイナリファイルは、他のファイルよりも「ブラックボックス」的な存在です。画像ファイルの閲覧、音声ファイルの再生、文書ファイルを適切なソフトウェアパッケージで開くことができます。しかし、バイナリーファイルはより困難です。
例えば、"hello "と "wd "というファイルはバイナリ実行ファイルである。それらはプログラムである。wd.o "というファイルは、オブジェクトファイルです。コンパイラは、ソースコードをコンパイルすると、1つまたは複数のオブジェクトファイルを作成します。これには、完成したプログラムを実行したときにコンピュータが最終的に実行するマシンコードや、リンカーに関する情報などが含まれています。リンカは、各オブジェクトファイル内のライブラリへの関数呼び出しを検査する。プログラムが使用するあらゆるライブラリにリンクされます。この処理の結果が実行ファイルです。
"monitor.exe "というファイルは、Windows上で動作するようにクロスコンパイルされたバイナリ実行ファイルです。
file wd file wd.o file hello file watch.exe最後の1つは、「monitor.exe」ファイルが、Microsoft Windowsのx86シリーズプロセッサ用のPE32+実行可能コンソールプログラムであることを示しています。 PEとは、Portable Executable Formatの略で、32ビット版と64ビット版があり、PE32が32ビット版、PE32+が64ビット版となります。
他の3つのファイルは、ELF(Executable and Linkable Format)ファイルとして識別されます。実行ファイルやライブラリなどの共有オブジェクトファイルの規格です。ELFのヘッダー形式については、まもなく学習します。
2つの実行ファイル("wd "と "hello")がLinux Standard Base(LSB)共有オブジェクトとして識別され、オブジェクトファイル "wd.o" は、LSB リロケータブルファイルとして識別されます。実行可能」という言葉はどうやら存在しないようです。
オブジェクトファイルは再配置可能であり、その中のコードは任意の場所でメモリにロードすることができます。実行ファイルはリンカによってオブジェクトファイルから生成され、この機能を継承しているため、共有オブジェクトに分類されます。
これにより、ASMR(Address Space Layout Randomisation)システムは、実行ファイルを任意のアドレスのメモリにロードすることができます。標準実行ファイルのヘッダーファイルには、メモリにロードする場所を示すロードアドレス・コードが記載されています。
ASMRはセキュリティの技術です。実行ファイルを予測可能なアドレスでメモリにロードすると、攻撃に対して脆弱になります。攻撃者は常に侵入口と機能の場所を把握しているからです。ランダムなアドレスに配置されたスタンドアロン実行可能ファイル(PIE)は、この感度を克服しています。
gccコンパイラでコンパイルし、-no-pieオプションを指定すると、通常の実行ファイルが生成されます。
o(出力ファイル)オプションで、実行ファイルの名前を指定することができます。
gcc -o hello -no-pie hello.c新しい実行ファイル上でこのファイルを使用し、何が変わったかを確認します。
file hello実行ファイルのサイズは従来と同じ(17KB)です。
ls -hl helloバイナリファイルは、標準的な実行ファイルとして認識されるようになりました。これはあくまでデモンストレーションのために行っています。このようにコンパイルしてしまうと、ASMRの良さが全くなくなってしまいます。
サンプルのHelloプログラムは17kbですから、大きいとは言い難いのですが、何事も相対的なものです。ソースコードは120バイトです。
cat hello.cターミナルウィンドウに文字列を表示するだけでよい場合、バイナリファイルの拡張子はどうなりますか?ELFのヘッダがあることは知っていますが、64ビットのバイナリファイルに対して64バイトしかありません。明らかに、これは別の問題であるに違いない。
ls -hl helloバイナリファイルの中身を知るための簡単な第一歩として、stringsコマンドでスキャンしてみましょう。
strings hello | lessバイナリファイルには「Hello, geek world!」しか書かれていない。「をソースコードから削除しました。その多くは、バイナリ内の領域のラベルや、共有オブジェクトの名前、リンク情報などである。ライブラリには、バイナリが依存するライブラリや、そのライブラリに含まれる関数が含まれます。
lddコマンドは、バイナリファイルの共有オブジェクトの依存関係を表示します。
ldd hello出力には3つのエントリがあり、そのうちの2つはディレクトリパスを含んでいます(1つ目は含んでいません)。
readelfユーティリティと-h(ファイルヘッダ)オプションを使って、ELFヘッダのチェックとデコードを行うことができます。
readelf -h helloタイトルで説明しています。
すべてのELFバイナリファイルの最初のバイトは、16進数の値0x7Fに設定されています。 次の3バイトは、0x45、0x4C、0x46に設定されています。 最初のバイトは、ファイルがELFバイナリファイルであることを識別するためのフラグです。これを明確にするために、次の3バイトをASCIIで "ELF "と表記しています。
その他の項目は、バイナリファイルの領域とセクションのサイズと数であり、その位置を計算することができる。
バイナリファイルの最初の8バイトを素早く表示するためにhexdumpを使用すると、ファイルの最初の4バイトに署名バイトと「ELF」文字列が表示されます。C(canonical)オプションでバイトのASCII表現とその16進数値を、-n(number)オプションで表示するバイト数を指定することができます。
hexdump -C -n 8 hello詳細を見たい場合は、objdumpコマンドと-d(disassemble)オプション:を使用します。
objdump -d hello | lessこれは、実行可能なマシンコードを逆アセンブルし、アセンブリ言語に相当するコードとともに16進数バイトで表示するものです。各行の最初のバイのアドレス位置は、左端に表示されています。
これは、アセンブリ言語が読めるか、裏側で何が起こっているのか興味がある場合のみ有効です。出力が多いので、少ないところに流しています。
バイナリファイルをコンパイルする方法はたくさんあります。例えば、デバッグ情報を入れるかどうかは、開発者が選択します。また、バイナリーのリンク方法は、その内容やサイズに影響を及ぼします。バイナリ参照が外部依存としてオブジェクトを共有する場合、その依存が静的にリンクされているオブジェクトよりも小さくなります。
ここで紹介したコマンドは、ほとんどの開発者がすでに知っている。しかし、他の人にとっては、バイナリー・ブラックボックスの中身を簡単に調べる方法を提供してくれるものです。