Shigeaki Matsumura

CEO of Backflip180, LLC.

API Spooferによる時刻の制御

はじめに

ここでは、API Spooferを使ってdateコマンドが返す時刻を制御します。 通常、dateコマンドが返す時刻を制御するには、root権限でdateコマンドを実行してシステムの時刻を変更する必要があります。 root権限がない状況ではこの方法を使い辛いでしょう。 しかし、今から紹介するAPI Spooferを使った方法はユーザー権限で行えるため、使い勝手がよい便利な方法です。

API Spooferについて

API Spooferは実行形式に対してスプーフィングするためのコードを自動生成します。 ある実行形式が共有ライブラリに依存している関数(API)を抜き出し、それらの関数のラッパー用のコードを生成します。 生成されたコードは、各関数がデフォルトで元の関数を呼び出すようになっているため、該当する関数のコード書き換えることで、任意のデータをアプリケーションに流し込んだり、取得することが可能になります。

API Spooferのインストール

まず、Pythonの2.7.xがインストールされていることを確認します。

$ python -V
Python 2.7.3

API Spooferv0.0.2をダウンロードします。 ダウンロードしたら解凍し、インストールを行います。

$ curl https://nodeload.github.com/matsu911/api_spoofer/tarball/v0.0.2 | tar xvzf -
$ cd matsu911-api_spoofer-c97e315/
$ python setup.py install

インストールに失敗する場合には、sudoでinstallを実行する必要があるかもしれません。 インストールに成功しているか、次のコマンドで確認しましょう。

$ which api_spoofer
/usr/local/share/python/api_spoofer

このように、api_spooferコマンドがインストールされたパスが表示されれば成功です。 環境によっては、環境変数PATHにapi_spooferがインストールされたパスを追加する必要があるかもしれません。

dateコマンドの時刻を制御する

ここでは、API Spooferを使ってdateコマンドが返す時刻を制御します。 まず、dateコマンドを実行してみましょう。

$ date
2012年 10月10日 水曜日 10時49分19秒 JST

このように実行したときの時刻が表示されます。 この表示される時刻を任意の時刻に制御できるようにします。 最初にdateコマンドの絶対パスを確認しておきます。

$ which date
/bin/date

/bin/dateがdateコマンドのパスであることがわかります。 次に、スプーフィングを行うためのコードテンプレートを生成します。

$ api_spoofer /bin/date > date_spoofer.c

dateコマンドはOSが提供する時刻を返すAPIであるclock_gettimeを呼び出すことで、OSから時刻を取得し、表示します。 clock_gettimeを次のように変更します。

int clock_gettime (clockid_t __clock_id, struct timespec *__tp)
{
  __tp->tv_sec  = 0;
  __tp->tv_nsec = 0;
  return 0;
}

編集後、date_spoofer.cをコンパイルし、共有ライブラリを作成します。

$ gcc -ldl -fPIC -shared date_spoofer.c -o date_spoofer.so

この作成したdate_spoofer.soを環境変数LD_PRELOADに設定することで、clock_gettimeを上書きすることができます。 つまり、clock_gettimeを上書きすることで、任意の設定した時刻をアプリケーション側に認識させることができます。

$ LD_PRELOAD=date_spoofer.so date
1970年  1月  1日 木曜日 09:00:00 JST

この方法を応用すれば、任意の時刻を自由に設定し、dateコマンドが認識する時刻を変更することが可能になります。 また、同様の方法で、様々なアプリケーションの時刻を制御し、時刻固有のイベントを人為的に発生させることも可能になります。