Win2000のNtQuerySystemInformationに16年来のバグ

DropBoxがCPU使い切ってフリーズするようになってしまったという報告を受けて調査して分かったことは
psutil._psutil_windows.pyd という、Python のバイナリがNtQuerySystemInformation のSystemProcessInformation命令でぐるぐる回ってることでした。

たいぶろぐ [Rainmeter-dev] Rainmeter on Windows 2000

取得には全プロセス分のバッファが必要になりますが、プロセス数×構造体のサイズ(+α)という単純な方法ではダメなようです。必要なバッ
ファサイズはNtQuerySystemInformation
APIを呼び出すことで取得できるとドキュメントには記載されていますが、どうもWindows
2000では必ず0が返ってくる
ようで(XPだとちゃんと必要なバッファサイズが返ってくる)、仕方ないので、成功するまでバッファサイズを
16KB分から倍々に増やしていくようにしています。

|。・ω・)。・ω・)。・ω・)な、なんだってー!?

そりゃ、ループするわ。

というわけで、コード書きました

_declspec(naked) _declspec(dllexport) int WINAPI NtQuerySystemInformation(int x,void *y,int s,int *ss){
    _asm{
          mov    eax,00000097h
          lea    edx,[esp+04h]
          int    2Eh
        cmp [esp+4],5
        jnz ER
        cmp eax,0xc0000004
        jnz ER
        mov ecx,DWORD PTR[esp+10h]
        test ecx,ecx
        jz ER
        mov ecx,DWORD PTR[ecx]
        test ecx,ecx
        jnz ER

        push ebp
        mov ebp,esp
        sub esp,0xc

要するに NtQuerySystemInformationよんで
第一パラメータがSystemProcessInformationの場合でなおかつ結果が 0xc0000004 (STATUS_INFO_LENGTH_MISMATCH)だった場合で、最終パラメータがNULLじゃなかった場合に、
適切な領域を返すように処理を追加。

int    2Ehを見てわかるように本来 NTOSKRNL.EXE 側の処理なのですが、ちょっとデバッグするには無理があるのでNTDLL上で修正コードを書きました。

拡張カーネル v2.6cより変更が反映されています。

※ v2.6cに不具合があったため 20:30に v2.6c2に差し替えてあります

おすすめ

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です