いずれにせよ、これは Windows の内部についての良い質問ですが、今私が興味を持っている理由は、それが私にとって実際的な質問になったからです。私が有料の仕事をしている場所には、それぞれが異なる Windows バージョンと異なるデバッガーを備えた 3 台のコンピューターがあり、この IFEO トリックを使用すると、デバッガー自体がデバッグされ、OP を悩ませるのとまったく同じ循環性に閉じ込められているようです。
デバッガーは通常、この循環をどのように回避しますか? まあ、彼ら自身はそうではありません。Windowsはそれらを回避します。
しかし、最初に循環性を見てみましょう。簡単なデモンストレーションは、PowerShell の調合ではほとんど役に立たず、calc.exe は以前とは異なります。Debugger
代わりに の値をに設定しましょnotepad.exe
うc:\windows\system32\cmd.exe /k
。notepad.exe
Windows はこれを、実行しようとすると通常は実行する必要があることを意味すると解釈しますc:\windows\system32\cmd.exe /k notepad.exe
。notepad.exe
CMD は、これを実行してハングアップすることを意味すると解釈します。しかし、この実行も にnotepad.exe
変わりc:\windows\system32\cmd.exe /k notepad.exe
ます。タスク マネージャーには、すぐに何百もの cmd.exe インスタンスが表示されます。(良いニュースは、それらがすべて 1 つのコンソールにあり、一緒に殺すことができるということです。)
/k
OPの質問は、子を実行するためのCMDとその(または)スイッチがなぜ/c
デバッガーの値で循環するのかということですが、たとえば、WinDbgは循環しません。
ある意味では、答えは文書化されていない構造の 1 ビットにまで及びます。PS_CREATE_INFO
これは、関数のユーザー モードとカーネル モードの間で交換されますNtCreateUserProcess
。この構造は、一部のサークルではかなりよく知られていますが、彼らがその方法について言及しているようには見えません。構造は Windows Vista にさかのぼると思いますが、Microsoft のパブリック シンボル ファイルからは Windows 8 まで、さらにはカーネルからではなく、Internet Explorer コンポーネントの URLMON.DLL などからは不明です。
とにかく、PS_CREATE_INFO
構造体の最新の形式では、オフセット 0x08 (32 ビット) または 0x10 (64 ビット) の 0x04 ビットは、カーネルがデバッガー値をチェックするかどうかを制御します。シンボル ファイルは、このビットが Microsoft ではIFEOSkipDebugger
. このビットがクリアされていて、Debugger 値がある場合、NtCreateUserProcess
失敗します。PS_CREATE_INFO
構造体を介したその他のフィードバックはKERNELBASE
、 の処理のためCreateProcessInternalW
に、デバッガーの値を独自に調べて、NtCreateUserProcess
(おそらく) 他の実行可能ファイルとコマンド ラインに対して再度呼び出すように指示します。
代わりにビットが設定されている場合、カーネルはデバッガーの値を気にせず、NtCreateUserProcess
成功することができます。ビットが通常どのように設定されるKERNELBASE
かは、呼び出し元がプロセスを作成するだけでなく、新しいプロセスのデバッガーになることを具体的に要求しているためです。つまり、プロセス作成フラグにDEBUG_PROCESS
またはを設定しています。DEBUG_ONLY_THIS_PROCESS
これが、循環性を回避するためにデバッガー自体が何もしないということです。Windowsは、実行可能ファイルをデバッグしたいという理由だけでそれを行います。
Debugger 値を実行可能 X のイメージ ファイル実行オプションと見なす 1 つの方法は、値が存在するということは、X がデバッガー以外で実行できないことを意味し、値の内容がそれを実行する方法を示している可能性があるということです。ハッカーは以前から気づいていましたが、カーネルのプログラマーもかなり前から気づいていたように、コンテンツでデバッガーを指定する必要はなく、Y を実行する代わりに X を実行しようとするように値を調整することができます。 Y が X をデバッグする (またはデバッガーの値を無効にする) 場合を除き、X を実行します。また、X を実行しようとするすべての試みが代わりに Y を実行するわけではないこともあまり知られていません。デバッガが X をデバッグ対象として実行しようとしても、迂回されません。