API Monitorによる解析とその対策

コラム概要

■こんな方におすすめ:

作成したプログラムの解析ツールを求めている
解析ツールからの簡単な対策方法を知りたい

■難易度:★☆☆

■ポイント:

  • APIが使用されているプログラムの解析ができるツールがある
  • 引数や戻り値が変更できる
  • 解析を対策する方法が存在する

1.はじめに

前回のコラムまではFridaのご紹介でした。
本コラムではAPI Monitor (http://www.rohitab.com/apimonitor) という解析ツールを用いて解析する方法と
その対策について解説します。

2.API Monitorとは

プログラムによって呼び出されるAPIの監視や制御ができる無料のソフトウェアです。
呼び出されるAPIやその引数などのパラメータ、API実行後の戻り値の取得や変更ができ、
プログラムの動作確認およびデバッグを行えます。

API Monitorの特徴
・32bit/64bit両方のプログラムに適用できる。
・モニタリングするAPIを選択できる。
・APIのパラメータや戻り値を取得できる。デコード機能を使用することでパラメータを文字列に変換できる。
 (ex. CreateFile の第二引数 dwDesiredAccess が数値から GENERIC_READなどに。)
・APIのパラメータや戻り値の構造体や配列を表示できる。
・APIのコールツリーを表示できる。
・API呼び出し時にブレイクポイントを設定できる。
・メモリエディタを使用できる。  ・・・・

解析ツールとしての用途が期待できます。
マルウェアの解析などで活躍しているこのツールを用いて、以下の章でプログラムの解析をしてみたいと思います。

3.API Monitorを用いての解析

下記は日時を表示するプログラムの実行結果です。

2024/05/28 09:07:09
2024/05/28 09:07:12
2024/05/28 09:07:15
2024/05/28 09:07:18
2024/05/28 09:07:21

GetLocalTime というWindows APIを使用してプログラムを作成しました。
そのプログラムの一部を抜粋してご紹介します。

while (1) {
        GetLocalTime(&st);
        printf("%04d/%02d/%02d %02d:%02d:%02d\n",
            st.wYear, st.wMonth, st.wDay,
            st.wHour, st.wMinute, st.wSecond);
    Sleep(3000);
    }

API Monitorでプログラムをモニタリング対象にした後、API FillterでGetLocalTime を選択します。

図1.モニタリング対象のAPI

プログラムを実行すると下のように選択したAPIのキャプチャができます。

図2. モニタリング対象のAPIのキャプチャ

GetLocalTime にブレイクポイントを設定後、再度実行するとパラメータや戻り値が変更できるようになります。

下はブレイクポイントにヒットした際に出てくるポップアップ画面です。
ブレイクポイントはデフォルトのBefore のまま、Skip Call にチェックを入れて、 Continue を押すと

図3.Skip Callにチェックする
2024/05/28 09:03:18
2024/05/28 09:03:18

同じ日時を表示するようになります。

次にメモリを変更して5月から6月に変更してみます。
このときブレイクポイントは下のように After を選択しておきます。

図4.ブレイクポイントの設定をAfter にする

パラメータにカーソルを当てて右クリックすると下のようなポップアップがでてくるのでEdit Memoryを選択します。

図5. ポップアップ画面

GetLocalTime が返す月のデータを5から6に変更します。

図6.メモリの変更

Close 後、 Continue を選択すると6月に変更できました。

2024/05/28 09:03:18
2024/05/28 09:03:18
2024/06/28 09:05:13

以上からプログラムの解析に使用できることがわかりました。

4.API Monitorへの対策

時刻を表示する別のコードの一部を抜粋してご紹介します。

	FnGetLocalTime fnGetLocalTime = (FnGetLocalTime)GetProcAddress(hKernel32, "GetLocalTime");
	
    if (fnGetLocalTime == NULL) {
        fprintf(stderr, "Failed to get function addresses\n");
        return 1;
    }

    SYSTEMTIME st;
    while (1) {
        fnGetLocalTime(&st);
        printf("%04d/%02d/%02d %02d:%02d:%02d\n",
            st.wYear, st.wMonth, st.wDay,
            st.wHour, st.wMinute, st.wSecond);
        Sleep(3000);
    }

前章のコードとは違います。

比べてみると前章のコードは暗黙インポートを使用しており、
プログラムの実行時に必要なDLLが自動的にロードされ、APIを直接呼び出しています。
一方、上述のコードは明示インポートを使用しています。
この方法では、プログラムの実行時に必要なAPIを手動で取得して呼び出しています。

このようにコードを変更することでモニタリング対象に GetLocalTime を選択していても、
下のように表示されないのでキャプチャできなくなります。

図7.モニタリング対象のAPIのキャプチャ

解析を防ぐことができました。

5.まとめ

本コラムでは API Monitorという強力な解析ツールをご紹介しました。
このツールを使用すれば、呼び出されたAPIのあたりを付けることができるため、
デバッガより気軽にプログラムの解析が行えるかもしれません。
また、呼び出されたAPIのパラメータや戻り値の取得・変更ができますが、
同時にこのツールによる解析を防ぐ方法についてもご紹介しました。
解析対策の一つとして参考になれば幸いです。

6. 参考

API Monitor公式サイト:
http://www.rohitab.com/apimonitor


当サイトでは、アプリのセキュリティについて詳しくわかる資料をご用意しています。
アプリのセキュリティや対策についてご興味を持たれた方は、
ぜひダウンロードしていただけますと幸いです。

ダウンロード資料一覧

また、弊社では
アプリへの不正な解析・改ざん行為(クラッキング)を防ぐ対策製品
「CrackProof」の開発・販売を行っております。
詳しく話を聞いてみたいと思われた方は、
当サイトからお気軽にお問い合わせください。

お問い合わせはこちら