CEO of Backflip180, LLC.
ここでは、API Spooferを使ってdateコマンドが返す時刻を制御します。 通常、dateコマンドが返す時刻を制御するには、root権限でdateコマンドを実行してシステムの時刻を変更する必要があります。 root権限がない状況ではこの方法を使い辛いでしょう。 しかし、今から紹介するAPI Spooferを使った方法はユーザー権限で行えるため、使い勝手がよい便利な方法です。
API Spooferは実行形式に対してスプーフィングするためのコードを自動生成します。 ある実行形式が共有ライブラリに依存している関数(API)を抜き出し、それらの関数のラッパー用のコードを生成します。 生成されたコードは、各関数がデフォルトで元の関数を呼び出すようになっているため、該当する関数のコード書き換えることで、任意のデータをアプリケーションに流し込んだり、取得することが可能になります。
まず、Pythonの2.7.xがインストールされていることを確認します。
$ python -V
Python 2.7.3
API Spooferのv0.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がインストールされたパスを追加する必要があるかもしれません。
ここでは、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コマンドが認識する時刻を変更することが可能になります。 また、同様の方法で、様々なアプリケーションの時刻を制御し、時刻固有のイベントを人為的に発生させることも可能になります。