none
プロセス生成の検知について RRS feed

  • 質問

  • お世話になります。

    プロセスが新たにプロセスを生成する際に、生成を検知して、条件にマッチしたらプロセス生成を阻止するプログラムの作成をしたいのですが、いろいろと調べましたところ、(1)SetWindowsHookExを利用する、(2)CreateProcessなどの関数を利用しているプロセスのImport Address Tableを変更して自分で定義した関数をはさむ、(3)PsSetCreateProcessNotifyRoutineを利用する、の3種類の方法を見つけました。

    (1)SetWindowsHookExのプログラムを作りましたが、ウインドウが生成される際にフックをしているようなので、ウインドウのないプロセスの場合はプロセス生成の検知はできないように感じました。また、ウインドウ生成までプロセスが実行されてしまっているように感じましたので、実行される前に阻止する今回の目的からは外れているように感じました。
    (2)ではプロセス生成の関数がいくつもあることから、関数一覧に漏れがないかが不安です。
    (3)はプログラムを作ったことがなく、ドキュメントも少ないことから、今回作成しようとしているプログラムにマッチするかがわかりません。

    プロセス生成を制御する最適な方法がございましたら、アドバイス頂けないでしょうか。

    ・プロセス生成を検知
    ・プロセスが実行される前に条件文で実行可否を判定

    以上、よろしくお願いいたします。
    2016年10月28日 4:39

回答

  • (1) の方法については、ご認識のとおりだと思います。
    そもそもこの方法は Window Message を Hook するためのものなので、今回の目的には合致していないと思います。

    (2) の方については、これを実現するには API Hook を行う必要があります。
    ただし、ご自身が提案している IAT (Import Address Table) の書き換えだけでは不十分です。
    IAT の書き換えで Hook できるのは、モジュール ビルド時にリンカにより解決された外部参照だけです。
    LoadLibrary() / GetProcAddress() 経由で呼び出される API コールに対しては、IAT の書き換えは意味を持ちません。
    さらに、CreateProcess() や CreateProcessAsUser() などの Win32 API はその名のとおり単なる Interface であるため、これ以外の関数コールでプロセスが生成される場合もあり得ます。
    どういうことかというと、Win32 API である CreateProcess() や CreateProcessAsUser() は、ntdll.dll に実装されている Windows Native API である ZwCreateUserProcess() (ntdll!ZwCreateUserProcess ルーチン) を呼び出すことによって、プロセスの生成を実現しています。
    (さらに ntdll!ZwCreateUserProcess ルーチンは、カーネル モード側の NT カーネル内に実装されている nt!ZwCreateUserProcess ルーチンを呼び出します。)
    つまり要望されている機能を実現するためには、Win32 API レベルでの API Hook では不十分であり、Native API レベルでのプロローグ コードの書き換えによる Hook が必要となります。
    ですが Native API を Hook する方法はとても高度なスキルを必要としますし、マイクロソフトも表向きにはこの方法を推奨していないはずです。
    さらに Native API を Hook すると、セキュリティ ソフトにウィルス感染として検知されてしまう等の、問題が発生することが予想されるため、難易度はかなり高いと思います。
    (もっとも世の中には、この方法で Hook を行っている製品はたくさんありますけど。)

    (3) の方法が、一番現実的だと思います。
    私も (3) の方法でプロセス生成を検出するための調査用プログラムを作って、結構重宝して使っております。
    マイクロソフトが提供している (というか、実際は SysInternals 。。。というか、Mark Russinovich さんですけど) "Process Explorer" ツールも、この方法でプロセス生成を検知しているようです。
    PsSetCreateProcessNotifyRoutine() は、Process and Thread Manager Routines と呼ばれる、カーネル モード側のソフトウェア用に提供されているサービス関数です。
    つまり PsSetCreateProcessNotifyRoutine() を利用するためには、カーネル モード側で動作するドライバ形式のソフトウェアを開発する必要があります。
    ドライバといっても、何かのデバイス用のドライバではなく、あくまでもカーネル モード ドライバと同じ「形式」のソフトウェアということです。
    カーネル モード ドライバの開発は、ユーザ モード側のアプリやサービスなどの開発とは異質ですが、Native API Hook よりははるかに簡単でまた確実にプロセス生成をキャッチできるので、一番お勧めです。
    • 回答としてマーク Shira X 2016年10月31日 0:49
    2016年10月28日 7:11

すべての返信

  • (1) の方法については、ご認識のとおりだと思います。
    そもそもこの方法は Window Message を Hook するためのものなので、今回の目的には合致していないと思います。

    (2) の方については、これを実現するには API Hook を行う必要があります。
    ただし、ご自身が提案している IAT (Import Address Table) の書き換えだけでは不十分です。
    IAT の書き換えで Hook できるのは、モジュール ビルド時にリンカにより解決された外部参照だけです。
    LoadLibrary() / GetProcAddress() 経由で呼び出される API コールに対しては、IAT の書き換えは意味を持ちません。
    さらに、CreateProcess() や CreateProcessAsUser() などの Win32 API はその名のとおり単なる Interface であるため、これ以外の関数コールでプロセスが生成される場合もあり得ます。
    どういうことかというと、Win32 API である CreateProcess() や CreateProcessAsUser() は、ntdll.dll に実装されている Windows Native API である ZwCreateUserProcess() (ntdll!ZwCreateUserProcess ルーチン) を呼び出すことによって、プロセスの生成を実現しています。
    (さらに ntdll!ZwCreateUserProcess ルーチンは、カーネル モード側の NT カーネル内に実装されている nt!ZwCreateUserProcess ルーチンを呼び出します。)
    つまり要望されている機能を実現するためには、Win32 API レベルでの API Hook では不十分であり、Native API レベルでのプロローグ コードの書き換えによる Hook が必要となります。
    ですが Native API を Hook する方法はとても高度なスキルを必要としますし、マイクロソフトも表向きにはこの方法を推奨していないはずです。
    さらに Native API を Hook すると、セキュリティ ソフトにウィルス感染として検知されてしまう等の、問題が発生することが予想されるため、難易度はかなり高いと思います。
    (もっとも世の中には、この方法で Hook を行っている製品はたくさんありますけど。)

    (3) の方法が、一番現実的だと思います。
    私も (3) の方法でプロセス生成を検出するための調査用プログラムを作って、結構重宝して使っております。
    マイクロソフトが提供している (というか、実際は SysInternals 。。。というか、Mark Russinovich さんですけど) "Process Explorer" ツールも、この方法でプロセス生成を検知しているようです。
    PsSetCreateProcessNotifyRoutine() は、Process and Thread Manager Routines と呼ばれる、カーネル モード側のソフトウェア用に提供されているサービス関数です。
    つまり PsSetCreateProcessNotifyRoutine() を利用するためには、カーネル モード側で動作するドライバ形式のソフトウェアを開発する必要があります。
    ドライバといっても、何かのデバイス用のドライバではなく、あくまでもカーネル モード ドライバと同じ「形式」のソフトウェアということです。
    カーネル モード ドライバの開発は、ユーザ モード側のアプリやサービスなどの開発とは異質ですが、Native API Hook よりははるかに簡単でまた確実にプロセス生成をキャッチできるので、一番お勧めです。
    • 回答としてマーク Shira X 2016年10月31日 0:49
    2016年10月28日 7:11
  • (修正前)お馬鹿さんの捕捉になりますが、以下が参考になるかもしれません。
    (修正後)Sysinternalsについては、以下が参考になるかもしれません。

    (MSのサイト)
    https://technet.microsoft.com/ja-jp/sysinternals/bb545021.aspx?f=255&MSPPError=-2147217396

    (本)
    https://www.amazon.co.jp/WINDOWS-SYSINTERNALS-%E5%BE%B9%E5%BA%95%E8%A7%A3%E8%AA%AC-Microsoft-Press/dp/4822294641

    SysInternals のいくつかは自分もたまに使ってます(フォントを大きくしてくれ)。

    • 編集済み 仲澤@失業者 2016年10月28日 10:57 ご指摘を受けたので文面修正しました。
    2016年10月28日 7:39
  • 詳細に解説していただきありがとうございます。
    PsSetCreateProcessNotifyRoutine()を利用してプログラムを作成してみようと思います。
    2016年10月31日 0:49