\r\n\r\n

linuxのコマンドラインからバイナリファイルを見る方法

謎のファイルはありませんか? linuxのファイルコマンドを使えば、どんなファイルかすぐにわかります。バイナリファイルであれば、その詳細を確認することができます。分析に役立つファイルが揃っています。これらのツールの使い方を紹介します...

Linuxのfileコマンドは、そのファイルの種類をすぐに教えてくれます。バイナリファイルであれば、その詳細を確認することができます。分析に役立つファイルが揃っています。これらのツールの使い方を紹介します。

ドキュメントの種類を特定する

ファイルは通常、パッケージがそのファイルの種類とその中のデータが何を表しているかを識別できるように、いくつかの特性を持っています。PNGファイルをMP3音楽プレーヤーで開いても意味がないので、ファイルに何らかのIDを持たせることは有用かつ実用的である。

これは、ファイルの先頭にある数個のシグネチャバイトである可能性があります。これにより、ファイルの形式と内容を指定することができます。ファイルアーキテクチャと呼ばれる、データ自体の内部組織のユニークな側面からファイルタイプが推測されることもあります。

Windowsなどの一部のOSでは、ファイル拡張子によってすべてがガイドされます。Windowsは、拡張子がDOCXのファイルは、実際にDOCXのワープロファイルであると思い込んでいます。 Linuxは、すぐにわかるように、そのようなことはありません。それは証拠を必要とし、ファイルの中から探します。

ここで紹介するツールは、この記事の調査に使用したmanjaro20、fedora21、ubuntu20.04のディストリビューションに既にインストールされています。それでは、fileコマンドで調査を開始します。

fileコマンドを使用する

カレントディレクトリには、ドキュメント、ソースコード、実行ファイル、テキストファイルなど、さまざまな種類のファイルが混在しています。

lsコマンドはディレクトリの内容を表示し、-hl(human readable size, long list)オプションは各ファイルのサイズを表示します。

ls -hl

これらのファイルを試し、何が得られるか見てみましょう。

file build_instructi***.odt file build_instructi***.pdf file COBOL_Report_Apr60.djvu

3つのファイル形式は正しく認識されていた。可能であれば、文書からより多くの情報を得ることができた。

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つ目は含んでいません)。

  • linux OS-vdso.so Inc: Virtual Dynamic Shared Objects (VDSO) は、ユーザー空間のバイナリーがカーネル空間のルーチン群にアクセスできるようにするカーネルメカニズムです。vdsoの共有オブジェクトはELF(Executable and Linkable Format)形式に準拠しており、実行時にバイナリに動的にリンクすることができます。カーネルがASMR方式をサポートしている場合、vdsoの機能は標準gnucライブラリによって提供されます。
  • libc.so Inc.6: GNUC ライブラリ共有オブジェクト。
  • /lib64/ld-linux-x86-64.so.2: このバイナリが使用したいダイナミックリンカーです。ダイナミックリンカーは、バイナリにどのような依存関係があるのかを発見するよう求めます。これらの共有オブジェクトをメモリに送り込みます。バイナリの実行を準備し、メモリ内の依存関係を見つけ、アクセスすることができます。そして、プログラムを開始します。

エルフのアバター

readelfユーティリティと-h(ファイルヘッダ)オプションを使って、ELFヘッダのチェックとデコードを行うことができます。

readelf -h hello

タイトルで説明しています。

すべてのELFバイナリファイルの最初のバイトは、16進数の値0x7Fに設定されています。 次の3バイトは、0x45、0x4C、0x46に設定されています。 最初のバイトは、ファイルがELFバイナリファイルであることを識別するためのフラグです。これを明確にするために、次の3バイトをASCIIで "ELF "と表記しています。

  • Class: バイナリファイルが 32 ビット実行形式か 64 ビット実行形式かを示す(1=32、2=64)。
  • Data: 使用されているエンディアンを示す。エンディアンエンコーディングは、マルチバイトの数値がどのように保存されるかを定義する。ビッグエンディアン符号化では、数値の最上位ビットが最初に格納されます。リトルエンディアン符号化では、数値の最下位ビットが最初に格納されます。
  • Version: ELFのバージョン(現在1)。
  • OS/ABI:使用されているアプリケーションバイナリインターフェースの種類を示す。2つのバイナリモジュール(プログラムと共有ライブラリなど)間のインタフェースを定義するものです。
  • ABIバージョン:ABIのバージョン。
  • Type: ELFバイナリファイルの種類。一般的な値は、再配置可能なリソース(オブジェクトファイルなど)にはETēng REL、-no pieフラグでコンパイルされた実行ファイルにはETēng EXEC、ASMRをサポートする実行ファイルにはETēng DYNを使用します。
  • Machine:命令セット構造。これは、バイナリファイルを作成するターゲットプラットフォームを示す。
  • Version: このバージョンのELFでは、常に1が設定されています。
  • エントリーポイントアドレス:実行を開始するバイナリファイル内のメモリアドレス。

その他の項目は、バイナリファイルの領域とセクションのサイズと数であり、その位置を計算することができる。

バイナリファイルの最初の8バイトを素早く表示するためにhexdumpを使用すると、ファイルの最初の4バイトに署名バイトと「ELF」文字列が表示されます。C(canonical)オプションでバイトのASCII表現とその16進数値を、-n(number)オプションで表示するバイト数を指定することができます。

hexdump -C -n 8 hello

objdumpと粒状性ビュー

詳細を見たい場合は、objdumpコマンドと-d(disassemble)オプション:を使用します。

objdump -d hello | less

これは、実行可能なマシンコードを逆アセンブルし、アセンブリ言語に相当するコードとともに16進数バイトで表示するものです。各行の最初のバイのアドレス位置は、左端に表示されています。

これは、アセンブリ言語が読めるか、裏側で何が起こっているのか興味がある場合のみ有効です。出力が多いので、少ないところに流しています。

コンパイル・リンク

バイナリファイルをコンパイルする方法はたくさんあります。例えば、デバッグ情報を入れるかどうかは、開発者が選択します。また、バイナリーのリンク方法は、その内容やサイズに影響を及ぼします。バイナリ参照が外部依存としてオブジェクトを共有する場合、その依存が静的にリンクされているオブジェクトよりも小さくなります。

ここで紹介したコマンドは、ほとんどの開発者がすでに知っている。しかし、他の人にとっては、バイナリー・ブラックボックスの中身を簡単に調べる方法を提供してくれるものです。

あなたが興味を持っているかもしれない記事

匿名者
匿名者

0 件の投稿

作家リスト

  1. admin 0 投稿
  2. 匿名者 0 投稿

おすすめ