none
タスクマネージャーに表示されないプロセスについて RRS feed

  • 質問

  • あるプログラム(a.exe)をWindows Server 2012R2で実行したのですが、タスクマネージャーの詳細タブに表示されません。

    しかしコマンドプロンプトからtasklistコマンドを実行したところ、リストにa.exeは存在しています。

    a.exeにタスクマネージャーに表示しないような特別なことはしておらず、なぜ表示されないのかが不明です。

    ちなみに…

    同じa.exeをWindows Server 2008で実行した場合は、タスクマネージャーのプロセスタブに表示されます。

    何か情報をお持ちの方はいらっしゃらないでしょうか?

    2016年5月25日 7:13

すべての返信

  • 質問時の情報が少なくあやふやでしたので、追加で調査した情報を追記します。

    ①起動方法

     a.exeは直接起動(ダブルクリック等)ではなく、別途C言語で作成したプログラムからのCreateProcess関数による起動です。
     この際、CreateProcess関数の引数は以下の通りでした。

     CreateProcess( NULL,
                     "a.exe",
                     NULL,
                     NULL,
                     FALSE,
                     NORMAL_PRIORITY_CLASS | DETACHED_PROCESS,
                     NULL,
                     NULL,
                     &si,
                     &pi);


    ②WinServer2008 と WinServer2012 での挙動の違い

     上記の方法でWinServer2008で起動した場合、タスクマネージャーにはa.exeが表示されますが、
     WinServer2012で起動した場合は、タスクマネージャーにはa.exeが表示されません。
     ただし、リソースモニターやコマンドプロンプトでのtasklistコマンドでは表示されます。

     またa.exeではなく別のb.exeを同様に起動した場合に、WinServer2008でもWinServer2012でも
     タスクマネージャーに表示されることも確認しました。
     a.exeもb.exeも、ともにWin32コンソールアプリとしてC言語で作成しています。

     b.exeは別サーバと通信を行うプログラム、a.exeはローカル上のプログラムを監視して動作して
     いなければ起動しなおすプログラムで、どちらも常駐して実行し続けるタイプのものです。


    ③調査情報
     CreateProcessの第6引数dwCreationFlagsに指定している DETACHED_PROCESS を CREATE_NO_WINDOW に
     変更することで、a.exeをWinServer2012のタスクマネージャーに表示できました。


    以上が現時点で調査して分かっている情報です。

    ここからは質問なのですが、
     質問1
       WinServer2012のタスクマネージャーには起動していても表示されないプロセスがあるのでしょうか?
     
     質問2
       CreateProcessの第6引数に指定したDETACHED_PROCESSとCREATE_NO_WINDOWの違いなのですが、
       下記の通りと認識しています。
        ・CREATE_NO_WINDOW
          プロセスをコンソールウィンドウなしで実行する
        ・DETACHED_PROCESS
          プロセスを親プロセスへのアクセス不可の状態で実行する

       ただ、この違いがタスクマネージャーへの表示に影響するようには思えません。
       何か他に違いがあるのでしょうか?

    以上、長くなってしまいました。
    何かご存知の方がいらっしゃいましたら、よろしくお願い致します。

    2016年5月31日 2:41
  • a.exe がゾンビ プロセス状態になっているのかも。
    私のあてにならない記憶では、Task Manager はゾンビ プロセスを表示しないはず。。。だったと思います。
    (OS に依存して、Task Manager の挙動が異なるのかも。)
    例えば、a.exe プロセスが Terminate していていも、a.exe の Process Handle や Thread Handle を「外部の」プロセスが保持し続けている (クローズしない) 場合、a.exe プロセスは終了状態でメモリ上に残り続けます。
    とりあえず、明示的にゾンビ プロセスを作ってみて、その際の挙動を確認してみては?
    • 回答の候補に設定 佐伯玲 2016年6月1日 1:58
    2016年5月31日 3:04
  • >お馬鹿 様

    返信ありがとうございます。

    ゾンビプロセスの可能性も考えたのですが…
    a.exeからは正常にログが出力されており、プログラムの動作自体も
    タスクマネージャーに表示されない以外は正常に見えるため、
    その可能性はなさそうです。

    また昨日の調査で分かった追加情報なのですが、
    タスクマネージャーに表示されるb.exeのDB接続処理部分を
    コメントアウトすると、タスクマネージャーに表示されなくなりました。


    ここまでの情報をまとめると、以下のような感じです。

    1.PG起動用exeからCreateProcess関数で起動したプロセスが
      タスクマネージャーに表示されない。
      リソースモニターやtasklistコマンドでは表示される。
      CreateProcess関数の第6引数はDETACHED_PROCESS。

    2.タスクマネージャーに表示されないのはWinServer2012の場合のみで
      WinServer2008ではタスクマネージャーに表示される。

    3.CreateProcess関数の第6引数をCREATE_NO_WINDOWに変更すると、
      タスクマネージャーに表示されるようになる。

    4.CreateProcess関数を変更する前でもタスクマネージャーに表示される
      プログラムもあるが、DB接続を行う処理をコメントアウトすると
      タスクマネージャーに表示されなくなる。

    5.CreateProcess関数からではなくダブルクリック等で直接起動した場合は
      タスクマネージャーに表示される。


    CreateProcess関数で起動するプロセスにDB接続処理を含むかどうかで
    タスクマネージャーに表示されるかどうかが変わるようですね…

    2016年6月1日 7:45
  • 私の環境(Windows Server 2012R2)で試したところ再現しました。

    CreateProcess(第6引数はDETACHED_PROCESS)で次のようなコードのプログラムを実行したところタスクマネージャーに表示されず。TaskListでは表示されました。

    #include <stdio.h>
    #include <windows.h>
    
    int main()
    {
    	while (true)
    	{
    		Sleep(1000);
    	}
    	return 0;
    }

    メッセージを処理してないからかな?と思い試しに下記のように修正するとタスクマネージャーに表示されました。

    #include <stdio.h>
    #include <windows.h>
    
    int main()
    {
    	MSG msg = { 0 };
    	while (true)
    	{
    		if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
    		{
    			if (msg.message == WM_QUIT) break;
    			DispatchMessage(&msg);
    		}
    	}
    	return 0;
    }


    あくまで仮定ですがメッセージを処理するようにすればタスクマネージャーに表示されるのかもしれません。

    追伸:2番目のプログラムでGetMessageを使ってましたがループのプログラムではPeekMessageのほうが適切かなと思いプログラムを修正しました。

    なんとなく User32.dll がプロセスのアドレス空間にマッピングされるかどうかで、挙動が変わってくるんじゃないかなぁ

    2016年6月1日 9:09
  • 断言はできませんが、もしかしたら a.exe プロセスの EPROCESS オブジェクトを書き換えているカーネル モード側のソフトウェアが存在するのかも。

    Windows で稼働中の個々のプロセスは EPROCESS オブジェクトとして表され、この EPROCESS 構造体メンバには LIST_ENTRY 構造体でプロセス チェーン情報が保持されています。
    Task Manager も "System Idle Process" の EPROCESS から順番に LIST_ENTRY 内のプロセス チェーンをたどり、稼働中プロセスの列挙を行っています。
    (この部分の詳細に関しては、こちらのサイトで詳しく解説されていますので、興味があったら参照してください。)

    つまり、個々の EPROCESS 内の LIST_ENTRY データとして保持されているプロセス チェーン情報を書き換えると、稼働中のプロセスであっても Task Manager から非表示にすることが可能なのです。
    (マルウェアの中には、これをやるものもある。)
    今回の現象がこれに該当するかは不明ですが、調べてみる価値はあるかも。

    すべてのプロセスの EPROCESS オブジェクトを確認するためには、カーネル モード接続でのライブ デバッグか、現象が発生している状態での「完全メモリ ダンプ」を採取しそれを調べるかの、いずれかになると思います。
    Hyper-V などの仮想環境があるのであれば、WinDBG を簡単にカーネル デバッグ接続させることができるので、ライブ デバッグがお勧めです。
    2016年6月1日 9:15