RtlSetProcessIsCriticalの正しくて間違った使い方

詳細はRtlSetProcessIsCriticalを参考にしてもらうとして、次のコードをコンパイルする。次に管理者権限で実行する。

#include <windows.h>
#include <winternl.h>
#include "util/EnablePrivilege.hpp" // http://www.geocities.co.jp/egggarden/_blog/EnablePrivilege.hpp.txt

typedef
NTSTATUS (WINAPI* RtlSetProcessIsCriticalType)(
    BOOLEAN bNew,
    BOOLEAN *pbOld,
    BOOLEAN bNeedScb);

int main()
{
  // カレントプロセスのSE_DEBUG_NAME特権を有効にする
  if (!util::EnableProcessPrivilege(::GetCurrentProcess(), SE_DEBUG_NAME, true))
  {
    return 1;
  }


  RtlSetProcessIsCriticalType RtlSetProcessIsCritical = 
    (RtlSetProcessIsCriticalType)::GetProcAddress(
      ::GetModuleHandle("ntdll"), "RtlSetProcessIsCritical");

  if (!RtlSetProcessIsCritical)
  {
    return 1;
  }
  BOOLEAN old = FALSE;
  NTSTATUS status = RtlSetProcessIsCritical(TRUE, &old, FALSE);
  return 0;
}

以上で、Windowsが死ぬ(デバッガを接続していない限り)。やったね!


SE_DEBUG_NAME権限が必要なので挙動としては真っ当なものだけど、あまりにも素直すぎて楽しかったのでちょっと紹介したくなった。


(要するに、この関数で操作されたプロセスが死ぬとWindowsのブレークが発生するようになる関数です。システムプロセスにはこれが設定されているみたい。)


(12/05追記)以下で類似の仕事ができます。

  • RtlSetProcessIsCritical
  • RtlSetThreadIsCritical
  • NtQueryInformationProcess with ProcessCriticalInformation 0x1D
  • NtSetInformationThread with ThreadCriticalInformation 0x12