Protectet Process #2

前回の続き。保護されたプロセスは、そのプロセスやスレッドハンドルの取得の際に、特定のアクセス権での取得を禁止する。その結果、たとえば以下のアクションの対象にならない。

  • リモートスレッドの作成
  • 仮想メモリ空間へのアクセス
  • アクティブな状態でのデバッガによるアタッチ
  • スレッドコンテキストの取得や変更

というわけで今度は通常プロセスを保護状態に変更してみる。対象は PID=3904 Game.exe。
これでYouのGame.exeもProtectedだZE☆

おk、ドライバ。

すばらしい。
欲張ってPsSetCreateProcessNotifyRoutineに呼応して、起動時から必ず保護されるように実装してみたが、こちらはプロセスの起動に失敗するようになってしまった。適当な保護開始のタイミングはどこなのかな。

実装

前回から続く、Protected Process 操作の実装は EPROCESS 内の ProtectedProcess フラグを切り替えるだけだったりする。以下はEPROCESS構造体定義(の簡略版)。

#include <pshpack1.h>
#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *) 0)->MEMBER)
struct V6KRNL
{
  struct EPROCESS
  {
    UCHAR       Spare0[0x0a0];
    _LIST_ENTRY ActiveProcessLinks; // +0x0a0
    UCHAR       Spare1[0x0a4];
    char        ImageFileName[16];  // +0x14c
    UCHAR       Spare2[0x0c8];
    union
    {
      ULONG     Flags2;             // +0x224
      struct
      {
        ULONG   JobNotReallyActive:         1;
        ULONG   AccountingFolded:           1;
        ULONG   NewProcessReported:         1;
        ULONG   ExitProcessReported:        1;
        ULONG   ReportCommitChanges:        1;
        ULONG   LastReportMemory:           1;
        ULONG   ReportPhysicalPageChanges:  1;
        ULONG   HandleTableRundown:         1;
        ULONG   NeedsHandleRundown:         1;
        ULONG   RefTraceEnabled:            1;
        ULONG   NumaAware:                  1;
        ULONG   ProtectedProcess:           1;     // <- こいつな
        ULONG   DefaultPagePriority:        3;
        ULONG   PrimaryTokenFrozen:         1;
        ULONG   ProcessVerifierTarget:      1;
        ULONG   StackRandomizationDisabled: 1;
      };
    };
    UCHAR       Spare3[0x034];
  };
  C_ASSERT(offsetof(EPROCESS, ActiveProcessLinks) == 0x0a0);
  C_ASSERT(offsetof(EPROCESS, ImageFileName)      == 0x14c);
  C_ASSERT(offsetof(EPROCESS, Flags2)             == 0x224);
  C_ASSERT(sizeof(EPROCESS)                       == 0x25c);
};
#include <poppack.h>

very easy.

じつはユーザーモードのPEB構造体にも IsProtectedProcess というフラグが用意されている。以下はPEB構造体定義の一部抜粋。

typedef struct _PEB {
  BYTE Reserved1[2];
  BYTE BeingDebugged;
  union
  {
    BYTE BitField;
    struct 
    {
      BYTE ImageUsesLargePages:          1;
      BYTE IsProtectedProcess:           1;    // <- こいつな
      BYTE IsLegacyProcess:              1;
      BYTE IsImageDynamicallyRelocated:  1;
      BYTE SkipPatchingUser32Forwarders: 1;
      BYTE SpareBits:                    3;
    };
  };
  PVOID Reserved3[2];
// ...
} PEB, *PPEB;

1 を設定すると確かに影響はあるらしいが、正確なところは未調査。少なくとも記事内のスクリーンショットカーネル空間のフラグのみを操作している。EPROCESSのフラグとPEBのフラグは自動で同期しないっぽい。